android handler源码解析
handler通信是一个内存共享的方案
Handler
public class Handler {
public Handler(@Nullable Callback callback, boolean async) {
// 拿到Looper里ThreadLocal储存的Looper对象
mLooper = Looper.myLooper();
}
}
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
threadlocal中的代码可以看出get()方法会返回一个Looper对象
public class ThreadLocal<T> {
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
}
上面的代码可以简化为:
public class ThreadLocal<T> {
public T get() {
ThreadLocalMap map = t.threadLocals;
if(map != null) {
return map.getEntry(this);
}
t.threadLocals = new ThreadLocalMap(this, firstValue)
return null;
}
}
可以看出handler构造方法里做的事,获取一个当前线程对应的Looper对象,并且这个Looper对象不能为空,否者抛出异常
public class Handler {
public Handler(@Nullable Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
}
}
因此,在子线程中创建Handler的时候要先构建一个当前线程对应的Looper,即执行Looper.prepare()
方法,并且每个线程该方法只能执行一次:
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
// 静态方法,和sThreadLocal结合就可以看出一个线程只对应一个Looper实例
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
}
此时注意,Looper中有有一个特殊的prepare方法,就是prepareMainLooper
public final class Looper {
// 静态方法
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
}
创建Looper时,构造方法中自动创建一个MessageQueue对象
public final class Looper {
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
}
}
2、发送一个Message消息
发送消息最后都会调用这个方法:
public boolean sendMessageAtTime(@NonNull 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);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) {
msg.target = this; // 这边的msg会持有一个handler对象
return queue.enqueueMessage(msg, uptimeMillis);
}
这里的message持有一个handler对象,所以使用内部类创建handler的时候有可能会造成内存
继续看源码,sendmessage最后会调用MessageQueue的enqueueMessage
方法,这个方法做的事就是往当前线程对应的MessageQueue队列中插入message:
boolean enqueueMessage(Message msg, long when) {
synchronized (this) { // 内置锁
msg.when = when;
Message p = mMessages; // 队列最前面的消息
boolean needWake;
if (p == null || when == 0 || when < p.when) { // 判断执行这个消息的时间是否在最前面的消息之前
// 插入到队列最前面
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
// 插入队列
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
MessageQueue是个单链表,优先级队列。
现在,消息已经被发送到消息队列里了,接下来就是消费这个事件。
4、消费事件
loop() 是一个静态方法,调用loop()方法就会开启一个死循环
public final class Looper {
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
}
}
通过这个死循环把消息回调给handler
public final class Looper {
public static void loop() {
for (;;) {
Message msg = queue.next(); // 取出队列最前面的消息
if (msg == null) {
//消息位空的时候才推出循环
return;
}
...
// msg.target就是将该消息发送进来的handler,通过这个handler把消息再回调回去
msg.target.dispatchMessage(msg);
}
}
最终会调用handleMessage(msg)
这个方法,也就是我们平时创建handler的时候重写的这个方法
public class Handler {
public void dispatchMessage(@NonNull Message msg) {
...
handleMessage(msg); // 最终会回到这个方法,
...
}
}
以上就是整个handler工作的基本的流程了。
总结
handler创建的时候同时会获取创建该handler的A线程所对应的looper对象,并调用loop方法不断循环从looper的messagequeue中取出消息,当handler在B线程里面发送消息的时候,会把message加入该handler的looper所对应的唯一messagequeue队列中去,前面说到的loop方法会回调A线程创建的handler的handlemessage方法,由此完成了message从子线程到主线程的切换。
上一篇: Android Handler 源码解析
下一篇: android源码解析--Handler
推荐阅读
-
Android 自定义相机及分析源码
-
解决Android使用Handler造成内存泄露问题
-
Android编程简易实现XML解析的方法详解
-
android handler.post和handler.sendMessage的区别和联系
-
Android编程简单解析JSON格式数据的方法示例
-
Android XmlPullParser 方式解析 Xml 文档
-
android针对json数据解析方法实例分析
-
Spring MVC源码(三) ----- @RequestBody和@ResponseBody原理解析
-
Android 实现IOS 滚轮选择控件的实例(源码下载)
-
基于Spring注解的上下文初始化过程源码解析(一)