Android onPause线程冻结应用程序

时间:2013-04-11 06:27:01

标签: android multithreading runnable resume onpause

我想制作秒表。我创建这样的秒表类。当我在另一个Activity中调用onPause时它的冻结应用程序。

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();
    }
}

}

我在另一个View中创建了类的实例。有人能解开我的问题吗?

stopky = new StopWatch(textFields);
stopky.run();

// do another stuff and register buttons with onClickListener and call
stopky.onPause(); // freeze application
stopky.onResume();

1 个答案:

答案 0 :(得分:1)

Object.wait()调用的run方法中,你不能Handler,它可能在主/ UI线程上运行。

整个Android应用程序通过在main / UI Thread中注册的简短方法进行协调。你也可能在那里注册你的秒表。在那里执行while循环并且同时处理来自用户界面的事件是不可能的。

快速解决方案是重新安排run方法并在下次调用时检查状态。基本上是这样的:

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);
    }
}

更好的方法是采用完全事件驱动的设计,避免在秒表停止时调用秒表。在这种情况下,您只需从Button的事件处理程序重新启动它。