Handler 允许你发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。每个 Handler 实例都与一个线程和该线程的消息队列相关联。当你创建一个新的 Handler 时,它会绑定到一个 Looper。它会将消息和可运行对象传递到该 Looper 的消息队列,并在该 Looper 的线程上执行它们。
Handler 有两个主要用途:
1、安排消息和可运行对象在将来的某个时间执行;
2、将要在与您自己的线程不同的线程上执行的操作排入队列。
主要场景是子线程完成耗时操作的过程中,通过 Handler 向主线程发送消息 Message,用来刷新 UI 界面。
消息驱动与 Handler
Android 是消息驱动的,实现消息驱动有几个要素
消息的表示:Message
消息队列:MessageQueue
消息循环,用于循环取出消息进行处理:Looper
消息处理,消息循环从消息队列中取出消息后要对消息进行处理:Handler
初始化消息队列
在 Looper 构造器中即创建了一个MessageQueue,Looper持有消息队列的实例。
发送消息
通过 Looper.prepare 初始化好消息队列后就可以调用 Looper.loop 进入消息循环了,然后我们就可以向消息队列发送消息, 消息循环就会取出消息进行处理,在看消息处理之前,先看一下消息是怎么被添加到消息队列的。
消息循环
Java 层的消息都保存在了 Java 层 MessageQueue 的成员 mMessages 中,Native 层的消息都保存在了 Native Looper 的 mMessageEnvelopes 中,这就可以说有两个消息队列,而且都是按时间排列的。
与 Handler 工作的几个组件 Looper、MessageQueue 各自的作用:
Handler:它把消息发送给 Looper 管理的 MessageQueue ,并负责处理Looper分给它的消息
MessageQueue:管理 Message,由 Looper 管理
Looper:每个线程只有一个Looper,比如UI线程中,系统会默认的初始化一个Looper对象,它负责管理 MessageQueue,不断的从MessageQueue中取消息,并将相对应的消息分给Handler处理。
Message 属于被传递,被使用的角色。Message 是包含描述和任意数据对象的“消息”,能被发送给 Handler。Message 包含 2 个 int 属性和一个额外的对象。 虽然构造器是公开的,但获取实例最好的办法是调用Message.obtain()或Handler.obtainMessage()。这样可以从他们的可回收对象池中获取到消息实例。一般来说,每个Message实例持有一个Handler。
MessageQueue 持有一列可以被 Looper 分发的 Message。一般来说由 Handler 将 Message 添加到 MessageQueue 中。 获取当前线程的 MessageQueue 方法是Looper.myQueue()。通过 Looper.getMainLooper() 获取到主线程的 looper。
Looper 与 MessageQueue 紧密关联。在一个线程中运行的消息循环。线程默认情况下是没有与之管理的消息循环的。 要创建一个消息循环,在线程中调用 prepare,然后调用 loop。即开始处理消息,直到循环停止。大多数情况下通过Handler来与消息循环互动。
相关参考
https://mdnice.com/writing/506ba98a73114a9885c1accb9e0996b5
https://www.bilibili.com/read/cv14158988
https://zhuanlan.zhihu.com/p/532104124
Handler防止内存泄露
原因
a).声明Handler为静态类,同时对于Activity的this引用封装成WeakReference
否则会导致匿名类引用了外部Activity,导致Activity不能被回收
b).如果这时对手机硬件进行横竖屏切换,讲导致Activity被创建,却不能被回收
措施
//移除所有消息
public void onDestroy()
{
mHandler.removeCallbacksAndMessages(null);
}
//静态类 弱引用
static class MyHandler extends Handler {
WeakReference<Activity> mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) {
mImageView.setImageBitmap(mBitmap);
}
}
}
Handler Looper 工作原理
// 成员
class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal()//why declare staic?
static Looper sMainLooper
final MessageQueue mQueue
final Thread mThread
}
//初始化 Looper.prepare()
if(sThreadLocal.get()!=null
throw new RuntimeException
sThreadLocal.set(new Looper(true))
//
public Looper( boolean quitAllowed)
{
mQueue = new MessageQueue(quitAllowed)
mThread = Thread.currentThread()
}
//开启事件循环
public static Looper.loop()
{
final Looper me = myLooper()//通过ThreadLocal获取Looper实例,通过Looper获取消息队列实例
final MessageQueue queue = me.mQueue
for (; ; ) {
Message msg = queue.next()//通过消息队列阻塞性地获取消息
if (msg == null) {// 跳出循环
return;
}
try {
msg.target.dispatchMessage(msg)//检查顺序:msg.callback->mCallback-> handleMessage
} finally {
}
msg.recycleUnChecked() //初始化msg属性,并放置在Message的sPool头部
}
}
最后Handler通过sendMessage将消息塞入mQueue队列
由Looper接收到了msg,然后调用Handler的dispatchMessage
Handler 检查mCallback->message.callback->mCallback的handleMessage