views:

184

answers:

1

I'm trying to write a blackberry app that is basically a stopwatch, and displays lap times. First, I'm not sure I'm implementing the stopwatch functionality in the most optimal way. I have a LabelField (_myLabel) that displays the 'clock' - starting at 00:00. Then you hit the start button and every second the _myLabel field gets updated with how many seconds have past since the last update (should only ever increment by 1, but sometimes there is a delay and it will skip a number). I just can't think of a different way to do it - and I am new to GUI development and threads so I guess that's why.

EDIT: Here is what calls the stopwatch:

_timer = new Timer();
_timer.schedule(new MyTimerTask(), 250, 250);  

And here is the TimerTask:

class MyTimerTask extends TimerTask {
long currentTime;
long startTime = System.currentTimeMillis();

public void run() {
synchronized (Application.getEventLock()) {
currentTime = System.currentTimeMillis();
long diff = currentTime - startTime;
long min = diff / 60000;
long sec = (diff % 60000) / 1000;
String minStr = new Long(min).toString();
String secStr = new Long(sec).toString();

if (min < 10)
 minStr = "0" + minStr;
if (sec < 10)
 secStr = "0" + secStr;

 _myLabel.setText(minStr + ":" + secStr);  
timerDisplay.deleteAll();
timerDisplay.add(_timerLabel);
 }
 }
}

Anyway when you stop the stopwatch it updates a historical table of lap time data. When this list gets long, the timer starts to degrade. If you try to scroll, then it gets really bad.

Is there a better way to implement my stopwatch?

+2  A: 

Here are a few tips:

  • keep track of the last "sec" value used to update the label, and exit from the run loop immediately if the newly-calculated "sec" value is the same - otherwise you're needlessly refreshing the UI with the same values which slows everything down
  • remove the synchronization in your run loop and just put the code that modifies the UI (setText call) in a UiApplication.getUiApplication.invokeLater() call (using an anonymous Runnable)
  • don't delete the re-add the label from the screen or maanger, you just need to call setText() and it should update - if it doesn't update then call invalidate() on the field and it will be redrawn
  • now that you've optimized your code and minimized the amount of actual UI drawing, it's safe to set the timertask interval to a lower value, such as 50ms, so that you have a smoother timer update

The most important thing to remember in making a fast UI is to only update the UI when you need to, and only update the fields that need to change. If you're calling methods like deleteAll() you're going to end up having the entire screen or manager refresh which is really really slow.

Marc Novakowski
Thank you so much!! I've modified it with all your suggestions and it is working MUCH better!!!
Michaela