Должен ли я вручную закрывать HandlerThreads, созданные моим приложением, при уничтожении действия?
Мое приложение состоит из одного Activity
, В этом упражнении я создаю несколько HandlerThread
s, которые работают в цикле для выполнения операций блокировки сокетов.
В настоящее время я отправляю сообщение о выходе всем HandlerThread
во время моего Activity.onDestroy()
,
Иногда, когда я открываю свое приложение, закрываю его и перезапускаю, происходит сбой (часто из-за отправки сообщения в поток обработчика, который не работает).
Мой вопрос: как правильно закрыть HandlerThread
когда я закрываю свое приложение? (Обратите внимание, что эти потоки могут блокироваться при работе с сокетом).
РЕДАКТИРОВАТЬ: Дополнительная информация: у меня есть пул потоков обработчиков, который инициируется в onCreate (нет проблем, когда я запускаю свое приложение в первый раз).
Каждый выполняемый цикл обработчика оборачивается
if (shouldRun) {
//body
}
else {
close();
}
заявление.
метод close удаляет все ожидающие сообщения и runnables и отправляет сообщение обработчику, который заставит его вызвать его looper.quit()
, Таким образом, если текущий поток обработчика заблокирован операцией ввода-вывода, только когда он завершит его, он выйдет ().
5 ответов
- Там должно быть какое-то несоответствие, иначе ваше приложение не рухнет. Вы уверены, что неработающий HandlerThread действительно является причиной? Разве вы не создаете объекты HandlerThread при создании вашей активности?
- Если ваши HandlerThreads ожидают выполнения операций ввода-вывода, я хотел бы попытаться прервать их. Простое удаление обратных вызовов и сообщений и просьба завершить работу Looper, даже отправка сообщений об ограничении в обработчик, ничего не изменит. Объект HandlerThread будет существовать до тех пор, пока Android не убьет процесс (который может произойти или не произойти). Это означает, что "ваше приложение будет собирать объекты зомби HandlerThread", которые, вероятно, недоступны. Если, конечно, вы не можете отправить этим HandlerThreads сообщение о завершении, которое приходит на канал, на котором они блокируются.
- Было бы намного лучше повторно использовать объекты HandlerThread. Сервис может быть подходящей моделью для этого.
- Кроме того, если потоки переживают вашу активность, вам нужно сообщить им, что их одноранговый узел связи (ваша активность) пропал. В противном случае они могут ссылаться на то, что уже прошло.
Да, было бы неплохо закрыть его. Также не забудьте удалить ваши обратные вызовы.
@Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
handler.getLooper().quit();
}
/**
* 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;
}
Выше приведен метод 'quit' исходного кода 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;
}
Ответ: "цикл - это метод while(true)". Он будет возвращаться до тех пор, пока не получит сообщение с нулевой целью.
Наилучшим подходом будет удаление обратных вызовов для ваших обработчиков в ваших действиях. onDestroy()
, Смотрите этот ответ для более:
/questions/12578302/kak-ostanovit-obrabotchik/12578315#12578315
HandlerThread останавливается при выходе из Looper. 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)