My OnStart() method should not get called because my onCreate() method will run infinitely. When OnCreate method runs, the runTimer() method gets called. This runTimer method will run infinitely because of handler.postDelayed. How is it that Android Studio is able to finish the infinite loop of the runTimer() method and then call OnStart() method?
// MY STOPWATCH APP
public class MainActivity extends AppCompatActivity {
private int seconds = 0;
private boolean running;
private boolean wasRunning;
@Override
// ON RUNNING MY APP FOR THE FIRST TIME THIS METHOD WILL GET CALLED FIRST.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
seconds = savedInstanceState.getInt("seconds");
running = savedInstanceState.getBoolean("running");
wasRunning = savedInstanceState.getBoolean("wasRunning");
}
runTimer();
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("seconds", seconds);
savedInstanceState.putBoolean("running", running);
savedInstanceState.putBoolean("wasRunning", wasRunning);
}
@Override
protected void onStop() {
super.onStop();
wasRunning = running;
running = false;
}
@Override
protected void onStart() {
super.onStart();
if (wasRunning) {
running = true;
}
}
//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;
}
//Sets the number of seconds on the timer.
private void runTimer() {
final TextView timeView = (TextView)findViewById(R.id.tv_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(Locale.getDefault(),
"%d:%02d:%02d", hours, minutes, secs);
timeView.setText(time);
if (running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
}
2
Answers
Why do you think that
runTimer()
will run indefinitely?handler.post()
andhandler.postDelayed()
add an object (yournew Runnable() {}
) to the message queue so the objectsrun()
method can be executed some time later.handler.post()
returns after adding the object to the message queue and therefore therunTimer()
andonCreate()
methods finish normally.Why "Message Queue"? Because the documentation says so:
https://developer.android.com/reference/android/os/Handler:
https://developer.android.com/reference/android/os/Handler#post(java.lang.Runnable):
https://developer.android.com/reference/android/os/Handler#postDelayed(java.lang.Runnable,%20long):
The whole point of using a
Handler
is to allow theRunnable
s that arepost()
ed to execute at some later point in time so that the current thread can continue its work.If the handler would execute the code within the
Runnable
directly (and blocking) then you could have written your code asnew Runnable() { /*...*/ }.run();
The handler.post will execute the Runnable on the handler thread, so runTimer() will exist after the call to handler.post()