I’m trying to port a PC Java program to the Android platform. The PC application uses a Swing.Timer to trigger an update every second. The associated listener, upon being called, gets new data from a database, then updates/redraws the screen using Graphics2D. I’ve learned how to use Android’s Canvas to draw the same things that I do with the PC application. Now I’m trying to learn how to use the equivalent Timer in Android. Unfortunately things don’t seem as straightforward on the Android platform. There are Timers, Handlers, AlarmManagers, and AsyncTasks. It would seem that AsyncTasks and AlarmManagers are more appropriate for one time (heavy duty?) tasks (right? wrong?) With regard to Timers and Handlers, I’ve seen many posts that say don’t use Timer, use Handlers instead. I found the approach used in the code below somewhere out there on the web and tried it. It seems like it should do what I want but it hangs the GUI whenever I click the stop button. Does anyone know why it does that?
Thanks times a million
Bill
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
dateFormat = new SimpleDateFormat(dateFormatString);
mHandler = new Handler();
mUpdateTimeTask = new MyRunnable();
Button button = (Button) findViewById(R.id.start_button);
button.setOnClickListener(new MyStartListener());
button = (Button) findViewById(R.id.stop_button);
button.setOnClickListener(new MyStopListener());
}
class MyStartListener implements View.OnClickListener {
public void onClick(View v) {
if (startUptimeMillis == 0L) {
startUptimeMillis = SystemClock.uptimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
}
};
class MyStopListener implements View.OnClickListener {
public void onClick(View v) {
mHandler.removeCallbacks(mUpdateTimeTask);
}
};
class MyRunnable implements Runnable {
public void run() {
final long start = startUptimeMillis;
long millis = SystemClock.uptimeMillis() - start;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
TextView tv = (TextView) findViewById(R.id.time_textView);
tv.setText(dateFormat.format(calendar.getTime()));
mHandler.postAtTime(this, (((minutes * 60) + seconds + 1) * 1000));
}
};
EDIT:
The problem is that postAtTime needs an absolute time at which to start, not a delay which is what my example is using. (See postAtTime here)
So I replaced all of the timing code above with the below and it does what I want!!:
long millis = SystemClock.uptimeMillis();
mHandler.postAtTime(this, millis+1000);
I don’t see how this could hang your app, unless you mean the start button doesn’t work any more… Perhaps you want to add this to your stop listener:
As far as Timers, AsyncsTask, etc… You are correct, the best way to program an event in the near future in Android is with a Handler and Runnable. AlarmManagers are not intended for fast callbacks like in animations and AsyncTasks are better for heavy duty computation.
I would like a to offer a simpler update Runnable: