Table of Contents
Chapter 4 notes
You should be fairly comfortable with Android Studio by now, so you can expect fewer videos going forward.
p. 119-120: Code block
Here are the Views in my content_stopwatch.xml
:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="92sp" android:text="" android:id="@+id/time_view" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/start" android:id="@+id/start_button" android:layout_below="@+id/time_view" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:onClick="onClickStart" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/stop" android:id="@+id/stop_button" android:layout_below="@+id/start_button" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:onClick="onClickStop" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/reset" android:id="@+id/reset_button" android:layout_below="@+id/stop_button" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:onClick="onClickReset" />
p. 122: Code blocks
Extra code to add to StopWatchActivity.java
(i.e., don't replace the entire file).
Member variables:
// Number of seconds displayed on the stopwatch private int seconds = 0; // Is the stopwatch running? private boolean running;
Methods:
//Start the stopwatch running when the Start button is clicked. public void onClickStart(View view) { running = true; } //Stop the stopwatch running when the Stop button is clicked. public void onClickStop(View view) { running = false; } //Reset the stopwatch when the Reset button is clicked. public void onClickReset(View view) { running = false; seconds = 0; }
p. 124
Here is some boilerplate repeating Handler
code:
final Handler handler = new Handler(); // Make a new Handler handler.post(new Runnable() { // Give handler a Runnable instance to execute ASAP @Override // Redefine the Runnables's run method public void run() { /* Stuff you * want to do * goes here. */ // Repost the Runnable (this) to run some time in the future. handler.postDelayed(this, MILLISECONDS_UNTIL_handler.post_IS_CALLED_AGAIN); } });
p. 127: Code blocks
To StopwatchActivity.java
add the following to the end of onCreate()
runTimer();
and the runTimer()
method:
private void runTimer() { final TextView timeView = (TextView)findViewById(R.id.time_view); final Handler handler = new Handler(); handler.post(new Runnable() { @Override public void run() { int hours = seconds/3600; int minutes = (seconds%3600)/60; int secs = seconds%60; String time = String.format("%d:%02d:%02d", hours, minutes, secs); timeView.setText(time); if (running) { seconds++; } handler.postDelayed(this, 1000); } }); }
Be sure you import android.os.Handler
and android.widget.TextView
.
p. 130
To rotate a stock AVD, use the Ctrl+F11
shortcut to switch to the previous layout orientation and Ctrl+F12
to switch to next layout orientation.
pp. 137-138: Code blocks
onSaveInstanceState
method to be added to StopwatchActivity
:
@Override public void onSaveInstanceState(Bundle savedInstanceState) { savedInstanceState.putInt("seconds", seconds); savedInstanceState.putBoolean("running", running); }
Code to be added to onCreate()
just before runTimer();
:
if (savedInstanceState != null) { seconds = savedInstanceState.getInt("seconds"); running = savedInstanceState.getBoolean("running"); }
p. 147: Code blocks
Additional member variable:
private boolean wasRunning;
Restore additional item in onCreate
's if (savedInstanceState != null)
block:
wasRunning = savedInstanceState.getBoolean("wasRunning");
Add additional item to onSaveInstanceState
:
savedInstanceState.putBoolean("wasRunning", wasRunning);
New methods:
@Override protected void onStop() { super.onStop(); wasRunning = running; running = false; }
@Override protected void onStart() { super.onStart(); if (wasRunning) { running = true; } }
p. 149: Expected app behavior
pp. 152-153
You may want to skip these pages until you have completed the app through p. 158.
pp. 154-158
Note that in the final version of this app, methods onStart
and onStop
are no longer needed. This is because onResume
will be called after onStart
and onPause
will normally be called before onStop
.
Coming up with a test case on an AVD that will partially obscure your app and put it into “Pause” is not trivial. However, if you start and restart the app, it should behave the same as before (even though you have now placed the run/don't run code in onResume
and onPause
.
Don't stress out if you aren't able to test that the changed code works when the app is “Paused” (i.e., not having focus), but do be sure it still works when “Stopped” and “Restarted”. And be sure to understand what Android is doing and the pause/resume process. (P.S., don't forget to read pp. 152-153.)
p. 162
The diagram is a good one to copy and tape next to your computer.