2013-04-11 4 views
1

Я хочу сделать секундомер. И я создаю такой класс секундомера. И когда я вызываю onPause в другое действие, это приложение для замораживания.Android onPause thread 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(); 
    } 
} 

}

и я создать экземпляр класса в другой вид, подобный. Может ли кто-нибудь объяснить мне, где проблема?

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 Thread.

Все Android-приложение координируется с помощью коротких методов, которые регистрируются в главном/пользовательском потоке. Возможно, вы тоже зарегистрируете свой секундомер. Невозможно выполнить петлю 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

как я могу это сделать? Как я должен модифицировать код? –

+0

Можете ли вы показать мне какой-нибудь простой пример? –

+0

Кстати, поскольку вы отметили свой Q «многопоточным»: просто потому, что у вас есть «Runnable», это не значит, что вы выполняете многопоточность. На самом деле, вы этого не делаете. Это означает, что вы можете полностью удалить синхронизацию. –