我应该在销毁活动时手动关闭我的应用程序创建的 HandlerThreads 吗?
Posted
技术标签:
【中文标题】我应该在销毁活动时手动关闭我的应用程序创建的 HandlerThreads 吗?【英文标题】:Should I manually close HandlerThreads created by my application when destroying the activity? 【发布时间】:2013-02-02 15:35:01 【问题描述】:我的应用由单个 Activity
组成。在此活动中,我创建了多个 HandlerThread
s,它们在循环中运行以执行套接字阻塞操作。
目前,我在Activity.onDestroy()
期间向这些HandlerThread
中的每个人发布了一条退出消息。
有时,当我打开我的应用程序,关闭它并重新启动它时,它会崩溃(很多时候是由于将消息发布到未运行的处理程序线程)。
我的问题是:当我关闭我的应用程序时,关闭 HandlerThread
的正确方法是什么?(请注意,这些线程可能会阻塞套接字操作)。
编辑:更多信息: 我有一个在 onCreate 中启动的处理程序线程池(当我第一次启动我的应用程序时没问题)。
每个处理程序可运行循环都用一个
包装 if (shouldRun)
//body
else
close();
声明。
close 方法删除所有待处理的消息和可运行的消息,并向处理程序发布一条消息,这将导致他调用其looper.quit()
。
这样,如果当前的处理线程被 IO 操作阻塞,只有当它完成它才会退出()。
【问题讨论】:
请分析崩溃原因。也许真正的原因是你的 HandlerThread 对象试图向 Activity 发布一些死掉的东西不再存在。您需要通知仍在运行的线程它们丢失了上下文。 【参考方案1】:是的,最好关闭它。还要确保删除您的回调。
@Override
public void onDestroy()
super.onDestroy();
handler.removeCallbacksAndMessages(null);
handler.getLooper().quit();
【讨论】:
但是当我重新启动我的应用程序时,我遇到了那些崩溃。我已经尝试了扩展答案。 你是否在重新启动时创建一个新的处理程序/线程并再次调用 Looper.prepare()/Looper.loop()? 据我了解,@Daniel 具有等待阻塞 I/O 操作的 HandlerThread 对象。要求 Looper 退出()不会立即生效。【参考方案2】: 你必须有一些不一致的地方,否则你的应用程序不会崩溃。你确定一个没有运行的 HandlerThread 真的是原因吗?创建 Activity 时不创建 HandlerThread 对象吗? 如果您的 HandlerThreads 正在等待 I/O 操作,我会考虑尝试中断它们。简单地删除回调和消息并要求 Looper 退出,甚至向 Handler 发送终止消息,都不会做任何事情。 HandlerThread 对象仍然存在,直到 android 终止进程(可能会发生也可能不会发生)。这意味着“您的应用程序将收集可能无法访问的僵尸 HandlerThread 对象”。当然,除非您可以向这些 HandlerThreads 发送一条终止消息,该消息到达它们阻塞的通道。 重用 HandlerThread 对象会更好。服务可能是执行此操作的正确模型。 此外,如果线程在您的 Activity 中存活,您需要通知它们它们的通信对等方(您的 Activity)已消失。否则,它们可能指的是已经消失的东西。【讨论】:
请使用堆栈跟踪发布异常。此外,核心问题是,您的 HandlerThread 对象是否维护对 Activity 的引用。【参考方案3】: /**
* 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源码的'quit'方法,直接调用即可。
为什么要叫quit?下面是HandlerThread.java源码的'run'方法。
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)'方法,它会返回直到收到一个目标为空的消息。
【讨论】:
【参考方案4】:最佳实践方法是在活动onDestroy()
中删除对处理程序的回调。有关更多信息,请参阅此答案:
https://***.com/a/5038542/1369222
【讨论】:
【参考方案5】:当 Looper 退出时,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 的一个很好的示例)
【讨论】:
据我了解,@Daniel 具有等待阻塞 I/O 操作的 HandlerThread 对象。要求 Looper 退出()不会立即生效。 可能,是的。在这种情况下,handlerThread.interrupt() 应该停止这些操作(但这并不特定于 HandlerThread)以上是关于我应该在销毁活动时手动关闭我的应用程序创建的 HandlerThreads 吗?的主要内容,如果未能解决你的问题,请参考以下文章