2013-02-18 5 views
9

Мое приложение состоит из одного Activity. В этой операции я создаю несколько HandlerThread, которые запускаются в цикле для выполнения операций блокировки сокетов.Должен ли я вручную закрывать HandlerThreads, созданные моим приложением, при уничтожении активности?

В настоящее время я размещаю сообщение о выходе для каждого из этих HandlerThread с на моем Activity.onDestroy().

Иногда, когда я открываю приложение, закрываю его и перезапускаю, он падает (много раз из-за публикации сообщения нитку обработчика, который не работает).

Мой вопрос: Каков правильный путь для закрытия HandlerThread, когда я закрываю приложение? (Обратите внимание, что эти потоки могут блокировать операцию сокета).

EDIT: Дополнительная информация: У меня есть пул Handler Threads, который инициируется в OnCreate (Нет проблем, когда я запуская мое приложение в первый раз).

Каждый обработчик работоспособным цикл обернуты с

if (shouldRun) { 
//body 
} 
else { 
close(); 
} 

заявления.

метод close удаляет все ожидающие сообщения и runnables и отправляет сообщение обработчику, который заставит его вызвать его looper.quit(). Таким образом, если поток текущего обработчика блокируется операцией ввода-вывода, только после его завершения он прекратит().

+0

Проанализируйте причину аварии. Возможно, истинная причина в том, что ваши объекты HandlerThread пытаются опубликовать что-то в Activity, которая больше не существует. Вам нужно сообщить тем, кто все еще работает, что они потеряли свой контекст. –

ответ

1
  • Вы должны иметь некоторую несогласованность там, в противном случае приложение не будет врезаться. Вы уверены, что причина HandlerThread, которая не работает? Разве вы не создаете объекты HandlerThread, когда создается ваша активность?
  • Если ваши операции HandlerThreads ждут операций ввода-вывода, я бы попытался их прервать. Просто удаляя обратные вызовы и сообщения и запрашивая Looper, чтобы завершить работу, даже отправляя сообщения о пробной обработке обработчику, ничего не выйдет. Объект HandlerThread по-прежнему будет находиться до тех пор, пока Android не убьет процесс (который может произойти или не произойти). Это означает, что «ваше приложение будет собирать объекты« HandlerThread »для зомби, которые, вероятно, недоступны. Если, конечно, вы не можете отправить те HandlerThreads сообщение о завершении, которое поступит на канал, на котором они блокируются.
  • Было бы намного лучше использовать объекты HandlerThread. Для этого может оказаться подходящей моделью.
  • Кроме того, если Threads выжить в своей деятельности, вам нужно сообщить им, что их коммуникационный сверст (ваша активность) ушел.В противном случае они могут ссылаться на то, что уже исчезло.
+0

см. Информацию, которую я добавил. –

+1

Пожалуйста, разместите исключение со стеком. Кроме того, основной вопрос заключается в том, что ваши объекты HandlerThread поддерживают ссылки в вашей Деятельности. –

3

Да, было бы неплохо закрыть его. Также не забудьте удалить свои обратные вызовы.

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    handler.removeCallbacksAndMessages(null); 
    handler.getLooper().quit(); 
} 
+0

Но потом я получаю эти сбои при перезагрузке своего приложения. Уже пробовал расширенный ответ. –

+0

Вы делаете новый обработчик/поток при перезапуске и снова вызываете Looper.prepare()/Looper.loop()? –

+0

Как я понимаю, @Daniel имеет объекты HandlerThread, которые ждут блокировки операций ввода-вывода. Попросить Looper выйти() не будет иметь немедленного эффекта. –

0

лучших практик подход будет удалить обратные вызовы для обработчиков в вашей деятельности onDestroy(). Смотрите этот ответ более:

https://stackoverflow.com/a/5038542/1369222

0

The HandlerThread останавливается, когда петлитель вышел. HandlerThread.getLooper(). Quit(), когда вы остановите свою деятельность. (См http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/app/IntentService.java#IntentService.ServiceHandler.%3Cinit%3E%28android.os.Looper%29 для хорошего примера правильного использования HandlerThread)

+0

Как я понимаю, @Daniel имеет объекты HandlerThread, которые ждут блокировки операций ввода-вывода. Попросить Looper выйти() не будет иметь немедленного эффекта. –

+0

возможно, да. В этом случае handlerThread.interrupt() должен остановить эти операции (но это не относится к HandlerThread). – njzk2

0
/** 
* Ask the currently running looper to quit. If the thread has not 
* been started or has finished (that is if {@link #getLooper} returns 
* null), then false is returned. Otherwise the looper is asked to 
* quit and true is returned. 
*/ 
public boolean quit() { 
    Looper looper = getLooper(); 
    if (looper != null) { 
     looper.quit(); 
     return true; 
    } 
    return false; 
} 

Выше «бросить» метод исходного кода HandlerThread.java, просто вызовите его непосредственно.

Почему следует назвать бросить курить? Ниже приведен метод «run» исходного кода HandlerThread.java.

public void run() { 
    mTid = Process.myTid(); 
    Looper.prepare(); 
    synchronized (this) { 
     mLooper = Looper.myLooper(); 
     notifyAll(); 
    } 
    Process.setThreadPriority(mPriority); 
    onLooperPrepared(); 
    Looper.loop();//always loop except for a Message with null target 

    mTid = -1; 
} 

Ответ «цикл является„методом в то время (правда)“, он не вернется, пока получит сообщение с нулевой целью.

Смежные вопросы