Handler
用于同一进程中的线程通信,Handler实例关联于一个线程以及其消息队列
应用
1. 安排Msg/Runnable在未来某一时间结点运行
2. 将动作交付于其他线程执行
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed at some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
初始化
Handler在初始化时 与 调用其初始化的线程绑定
这里Handler只是直接绑定到了Looper上,又怎么和线程关联的呢?
每个线程都有自己的Looper,一个Looper只允许绑定一个线程,由此绑定到Looper,相当于间接性绑定到线程上
发送消息
子线程调用Handler发送Msg,加入Handler持有的线程MsgQueue中,等待Handler持有线程异步处理
不是Handler只能绑定一个线程么为什么添加时需要互斥锁呢?
Handler只能绑定一个线程,但Looper又没说不能绑定多个Handler啊,可能在不同线程中,Handler同时发送Msg,从而有多线程竞争。(enqueueMessage方法时调用Handler线程调用,而不是Handler持有线程调用)
接收消息
子线程发送的消息添加到消息队列,然后在Handler持有线程中执行,实现将动作交付其他线程执行
内存泄漏
我们注意到Msg中target
会持有Handler实例,采用内部类的方式自定义Handler,会持有一个线程(外部类)实例,于是Thread多了一条引用链
以下问题来自于Stack Overflow,链接昨天没记,现在找不到了,呜呜呜
In Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.
在Android里,Handler 及其子类应当是static的,否则将会内存泄漏。进入消息队列的Msg持有其Handler,如果Handler是一个内部类,那么Handler还持有了外部类的引用,为了避免外部类内存泄漏,应当声明Handler子类为static并且持有外部类的弱引用
Handler’s are mainly used to post events to the Thread’s MessageQueue.Each Handler instance is associated with a single thread and that thread’s message queue.
so when you post a runnable with a delay, and exit from the activity, the MainThread will not be destroyed, as there are still events in the MessageQueue to be processed after a delay, so this can cause a memoryLeak as your anonymous innerclass of runnable is holding the reference of activity instance .
so make sure to remove all the messages in onStop() of Activity by calling
handler.removeCallbacksAndMessages(null);
this will clear all the pending message and callbacks before leaving your activity.
Handler主要用于发送Msg给线程的MsgQueue。每个Handler实例持有一个线程及其MsgQueue。
当延时提交一个Runnable,并在延迟的时间内退出Activity,而主线程仍在运行。由于Msg在一段时间延迟仍在MsgQueue中等待执行,由于匿名内部类Runnable持有退出Activity的引用,从而导致了内存泄漏。
为了保证在onStop()阶段移除所有Msg,可调用handler.removeCallbacksAndMessages(null);
在退出Activity退出前清除所有未执行的Msg和Callback