2013-04-11 121 views
1

我想製作秒錶。我創建這樣的秒錶類。當我在另一個Activity中調用onPause凍結應用程序。Android 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(); 
    } 
} 

}

,我在另一個視圖如創建類的實例。有人可以嘲笑我問題在哪裏嗎?

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

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

回答

1

你不能Object.wait()run方法從Handler叫,這可能是在主/ UI線程上運行。

整個Android應用程序通過短的方法進行協調,這些方法向主/ UI線程註冊。你可能也在那裏註冊你的秒錶。無法在那裏執行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的事件處理程序重新啓動它。

+0

我該怎麼辦?我如何修改代碼? – 2013-04-11 06:35:01

+0

你能告訴我任何簡單的例子嗎? – 2013-04-11 06:39:45

+0

順便說一句,既然你用「多線程」標記你的Q:只是因爲你有一個'Runnable'並不意味着你正在做多線程。事實上,你沒有。這意味着你可以完全刪除同步。 – 2013-04-11 07:05:23