Handler作为Android应用层开发,进程通信一大重点,可以说是使用最频繁的一个机制,不管是IntentService,ThreadHandler都绕不开它。本文详解Handler机制的内部源码
深入剖析Handler,没有看错,比别人更深更精准!
看本文可以回答你这几个问题:
-
UI线程的Looper在哪里创建?
-
MessageQueue真的是个队列吗?
-
延迟处理机制的原理?
-
Handler中的Message同步和MessageQueue同步?
一、Handler介绍
Handler在Android os包下,当我们创建Handler时,它会绑定一个线程,并且创建一个消息队列,通过发送Message或者Runnable对象到队列并轮询取出,实现关联。
我们常用的Handler功能是,定时执行Runnable或者处理不同线程通信的问题,比如UI线程和子线程等。
由此可见Handler内部机制中的几大元素:Handler,Message,MessageQueue,Looper,ThreadLocal等,接下来,分别查看它的内部源码。

二、Handler源码剖析
Handler作为封装对外的处理器,我们来看看它对外的接口内部是做了哪些操作。
1. Handler构造函数:
它的构造函数,我归纳为三种方式,分别是:
1.传入自定义Looper对象,
2.继承Handler实现Callback接口模式,
3.默认创建的Looper模式,
其中2,3是我们常用的,当然1和2也能同时使用,callback接口中实现handleMessage,用于我们自定义Handler是实现回调用的。还有个被hide隐藏的传参,async是否同步,默认是不同步,且不支持设置同步模式。
可以传入自定义的Looper,Callback接口
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
常规的构造方法如下:
-
其中FIND_POTENTIAL_LEAKS标签是检查“继承类是否为非静态内部类”标签,我们知道,非静态内部类持有对象,容易导致内存泄漏的问题,可以查看我的《Android内存优化分析篇》
-
mAsynchronous可以看到一直是false
public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
2. 创建Looper对象和mQueue消息队列
由上构造函数中调用Looper.myLooper();创建了Looper对象,并取用了新创建Looper对象内部的mQueue队列,详解下Looper分析
3. sendMessage
-
其中sendEmptyMessage通过obtion新获取了一个Message对象
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } -
发送消息:sendMessageDelayed—>sendMessageAtTime—>enqueueMessage
-
注意到,在调用sendMessageAtTime时,传入的时间值: 系统时钟+delayMillis
-
其中将 msg.target标记为当前Handler对象
-
最终调用了MessageQueue的enqueueMessage,看后面MessageQueue分析
//----------1 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } //----------2 public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } //---------3 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); } //----------4 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
4. removeMessages
从队列删除
5. post(Runnable r)
-
在getPostMessage中讲Runnable封装成了Message对象
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
6. dispatchMessage和handlerMessage
-
我们看到dispatchMessage调用了callback和handlerMessage分发Message结果
-
那么,前面我们看到了经常调用的sendMessage,那么回调是在什么时候调用的呢?
-
让我们接下来一起看看Looper类吧。
public v

最低0.47元/天 解锁文章
517

被折叠的 条评论
为什么被折叠?



