Android @ Kiowok

User Interface (UI) Thread

Timed Tasks (and Updating the UI Thread)

This example shows a simple timer -- it displays a simple count of the number of seconds that have elapsed since the app started, updated once per second.

Note that TimerTask (created on line // 1) will run on a separate thread. Specifically, the code code in the run method (line // 2) will be running a separate thread.

However, the TextView that we want to update -- textShowTimer -- needs to be updated on the UI thread. Therefore, in line // 3 we do not call textShowTimer.setText to try to set the text from the timer thread. Instead, we call the post method, textShowTimer.post that puts this runnable object (and its run method) on the user interface thread's message queue so that it will be run on the user interface thread.

Line //6 sets up a Timer object, and line //7 tells the timer to run the TimerTask's run method once per second.

For this code to work, you need to create:

  • a project named DemoTimer
  • the activity should be named DemoTimerActivity
  • the user interface needs a single TextView named textShowTimer

For more information on updating the UI thread, see this excellent article on the Android Developers Blog. Note especially the line that says that the Android UI toolkit is not threadsafe (which is why all changes need to be made from the single UI thread). Also useful is the official documentation on AsyncTask.

package com.example.demotimer;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class DemoTimerActivity extends Activity {
   TextView textShowTimer;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo_timer);

      textShowTimer = (TextView) findViewById(R.id.textShowTimer);
      startTimer();
   }

   private void startTimer() {
       final long startMillis = System.currentTimeMillis();

       TimerTask task = new TimerTask() {  // 1
           @Override
           public void run() {  // 2
               final long elapsedMillis = System.currentTimeMillis() - startMillis;

             // Can only change the UI on the UI thread
             textShowTimer.post(new Runnable() {  // 3
                 int elapsedSeconds = (int) elapsedMillis/1000;  // 4

                 @Override
                 public void run() {
                     textShowTimer.setText("Seconds: " + elapsedSeconds);  // 5
                 }
             });
           }
       };

       Timer timer = new Timer(true);  // 6 - true means to run as a daemon thread (app won't wait for thread's run to complete before terminating
       timer.schedule(task, 0, 1000);  // 7 - execute every second
   }
}
Top