3

So I'm trying to write a stopwatch app that displays time in milliseconds, but for some reason it won't work. Basically I have just a togglebutton that, after being pressed, starts printing the milliseconds from the start time to the current time... In the simulator though, the app locks up. What's wrong?

public class testing extends Activity {
/** Called when the activity is first created. */
Button start,stop;
long init,now,time;
TextView display;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test);
    display = (TextView) findViewById(R.id.chronometer1);
    final ToggleButton passTog = (ToggleButton) findViewById(R.id.onoff);
    passTog.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            init=System.currentTimeMillis();
            while(passTog.isChecked())
            {
                now=System.currentTimeMillis();
                time=now-init;
                display.setText("t: " + time);
            }

        }
    });
}

}

user1123530
  • 561
  • 3
  • 7
  • 17

2 Answers2

8

You definitely should not run a busy loop like you are doing inside the OnClickListener. That's why the app locks up. You need to let the rest of the system have its say. Also, it doesn't make sense to update the display more than once every 30 milliseconds or so, since that's about the fastest that the human eye can track. Also, you might want to suspend your timer when the activity is paused. Here's a version that does all that:

public class testing extends Activity {

    /** Called when the activity is first created. */
    Button start,stop;
    long init,now,time,paused;
    TextView display;
    Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler = new Handler();
        setContentView(R.layout.test);
        display = (TextView) findViewById(R.id.chronometer1);
        final ToggleButton passTog = (ToggleButton) findViewById(R.id.onoff);
        final Runnable updater = new Runnable() {
            @Override
            public void run() {
                if (passTog.isChecked()) {
                    now=System.currentTimeMillis();
                    time=now-init;
                    display.setText("t: " + time);
                    handler.postDelayed(this, 30);
                }
            }
        };
        passTog.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                init = System.currentTimeMillis();
                handler.post(updater);
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        paused = System.currentTimeMillis();
    }

    @Override
    protected void onResume() {
        super.onResume();
        init += System.currentTimeMillis() - paused;
    }
}
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 2
    wrong. OP wants to start counting on button click, not on creation of the activity – codeling Jan 01 '12 at 17:55
  • including good example now, thumbs up! But why do you initialize init *only* in onCreate? When looking at OP's question, I'd say he wanted to start the stopwatch on buttonclick, not on activity creation; or am I misunderstanding something here? – codeling Jan 01 '12 at 18:07
  • @nyarlathotep - My code doesn't initialize `init` in `onCreate` (any more). It is set when `onClick` executes. – Ted Hopp Jan 01 '12 at 18:10
  • ah yeah, missed that, was still in there a few minutes ago ;). Great job – codeling Jan 01 '12 at 18:11
  • That code has compile errors... I've modified it like [this](http://dl.dropbox.com/u/51147339/testing.java), it seems to be working fine... – user1123530 Jan 01 '12 at 18:56
  • @user1123530 - Good to know that you got it running. What were the compile errors? – Ted Hopp Jan 01 '12 at 19:19
  • Well, you tried to use passTog before it was declared, so I just moved the whole thing down. Thanks for everything, you've been very helpful :D – user1123530 Jan 01 '12 at 20:52
  • @user1123530 - Thanks for the feedback. I reorganized the code in case someone else wants to imitate it. – Ted Hopp Jan 01 '12 at 21:22
0

You put the setText() method in your onClick(), so will you click the button every second? Its not even a thread! Try the onTick() method of CountDownTimer class instead.

wattostudios
  • 8,666
  • 13
  • 43
  • 57