I want to make stopwatch. And i create stopwatch class like this. And when i call onPause in another Activity its freeze application.
public class StopWatch implements Runnable {
private Object mPauseLock;
private boolean mPaused;
private boolean mFinished;
private ArrayList<TextView> textFields;
private Handler mHandler = new Handler();
public StopWatch( ArrayList<TextView> textFields) {
mPauseLock = new Object();
mPaused = false;
mFinished = false;
this.textFields =textFields;
}
public void run() {
textFields.get(1).setText("progressing...");
if (!mPaused) {
mHandler.postDelayed(this, 1000);
}
synchronized (mPauseLock) {
while (mPaused) {
try {
mPauseLock.wait();
} catch (InterruptedException e) {
}
}
}
}
public void onPause() {
synchronized (mPauseLock) {
mPaused = true;
}
}
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();
}
}
}
and i create instance of class in another View like. Can somebody exmplain me where is problem?
stopky = new StopWatch(textFields);
stopky.run();
// do another stuff and register buttons with onClickListener and call
stopky.onPause(); // freeze application
stopky.onResume();
You can't Object.wait()
in a run
method called from a Handler
, which is probably running on the main/UI Thread.
The whole Android app is coordinated via short methods which register with the main/UI Thread. You're probably registering your stopwatch there, too. It's not possible to perform a while
loop there and at the same time process events from the user interface..
A quick solution would be to re-schedule your run
method and check the status the next time it gets called. Basically like so:
public void run() {
textFields.get(1).setText("progressing...");
if (!mPaused) {
// do what has to be done when stopwatch is running
mHandler.postDelayed(this, 1000);
} else {
// just re-schedule with a shorter delay
mHandler.postDelayed(this, 10);
}
}
An even better way would be to go for a fully event-driven design and avoid calling the stopwatch at all while it is stopped. In this case, you would simply re-start it from the Button's event handler.