源码第四篇--Android应用程序是经过消息来驱动的,Android某种意义上也能够说成是一个以消息驱动的系统,UI、事件、生命周期都和消息处理机制息息相关,而且消息处理机制在整个Android知识体系中也是尤为重要,在源码分析的路上Handler机制是必不可少的。若是你对Handler机制还不是特别了解的话,能够静下心来看一看这篇。安全
相关概念:在理解Handler机制以前,须要先熟知跟Hanlder相关的几个类:Handler、Message、Message Queue、Looper,这几个类之间的关系以下图:bash
2.MessageQueue:就是一个队列,特性就是“先进先出,后进后出”,每个Looper都会维护这样一个队列,并且仅此一个,这个队列的消息只能由该线程处理。多线程
3.Handler:Handler在sendMessage的时候会往消息队列里插入新消息。Handler的另一个做用,就是能统一处理消息的回调。并发
接下来开始讲解Hanldre机制的源码,源码将分为3部分说明,包括程序启动初始化、Loop的轮询机制、Handler消息的发送async
// 程序入口函数
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
// 主线程Loop初始化
Looper.prepareMainLooper();
// 初始化资源管理器
ActivityThread thread = new ActivityThread();
/**
* attach方法会建立一个Binder线程(具体是指ApplicationThread,该Binder线程会经过向
* Handler将Message发送给主线程)。咱们以前提到主线程最后会进入无限循环当中,
* 在没有在进入死循环以前会在这里建立Binder线程,这个线程会接收来自系统服务
* 发送来的一些事件封装了Message并发送给主线程,主线程在无限循环中从队列里拿到这
* 些消息并处理。(Binder线程发生的消息包括LAUNCH_ACTIVITY,PAUSE_ACTIVITY等等)
*
* 而且会在该方法中完成Application对象的初始化,而后调用Application的onCreate()方法
*/
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// 启动Looper的loop轮询方法
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
复制代码
所以在程序入口函数中,就完成了Looper的主线程初始化以及轮询方法的运行。ide
// 主线程Looper的初始化
public static void prepareMainLooper() {
prepare(false); // 实际上调用此方法初始化Looper
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper(); // 设置主线程Looper
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 将Looper设置到ThreadLocal中,具体后面再将
sThreadLocal.set(new Looper(quitAllowed));
}
// Looper构造方法
private Looper(boolean quitAllowed) {
// Looper在初始化时,会实例一个消息队列,此时Looper持有MessageQueue的引用
mQueue = new MessageQueue(quitAllowed);
// 当前Looper所在线程
mThread = Thread.currentThread();
}
public static void loop() {
// 获取当前Looper的实例对象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 获取当前Looper的消息队列
final MessageQueue queue = me.mQueue;
...
// 主线程开启无限循环模式
for (;;) {
// 获取队列中下一条消息并删除,可能会线程阻塞
Message msg = queue.next();
if (msg == null) {
return;
}
...
try {
//分发Message,
//这个Message会持有这个Handler的引用,并放到本身的target变量中,这样就能够回调咱们重写的handler的handleMessage方法。
/**
* 分发消息:
* msg.target是一个Handler对象,在Handler调用sendMessage方法时会设置此变量
* 所以就能够作到哪一个Handler发送的消息,就会经过哪一个Handler的分发消息方法
* dispatchMessage将消息从新回调到该Hanlder中
*/
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
// 将Message回收到消息池,下次要用的时候不须要从新建立,obtain()就能够了。
msg.recycleUnchecked();
}
}
复制代码
prepareMainLooper()方法实际上就是new了一个Looper实例并放入Looper类下面一个static的sThreadLocal静态变量中,同时给sMainLooper赋值,给sMainLooper赋值是为了方便经过Looper.getMainLooper()快速获取主线程的Looper,sMainLooper是主线程的Looper可能获取会比较频繁,避免每次都到 sThreadLocal 去查找获取。loop()方法 == 消息出队 + 分发给对应的Handler实例函数
注:此处有一个重要的概念ThreadLocal,后面具体分析oop
public void dispatchMessage(Message msg) {
// 若msg.callback属性不为空,则表明使用了post(Runnable r)发送消息
// 则执行handleCallback(msg),即回调Runnable对象里复写的run()
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 若msg.callback属性为空,则表明使用了sendMessage(Message msg)发送消息
// 则执行handleMessage(msg),即回调复写的handleMessage(msg)
handleMessage(msg);
}
}
// 直接回调Runnable对象里复写的run()方法
private static void handleCallback(Message message) {
message.callback.run();
}
// 注:handleMessage为空方法,在建立Handler实例时会复写该方法
public void handleMessage(Message msg) {
}
// Handler构造方法1
public Handler() {
// 调用Handler构造方法6
this(null, false);
}
// Handler构造方法2
public Handler(Callback callback) {
// 调用Handler构造方法6
this(callback, false);
}
// Handler构造方法3
public Handler(Looper looper) {
// 调用Handler构造方法7
this(looper, null, false);
}
// Handler构造方法4
public Handler(Looper looper, Callback callback) {
// 调用Handler构造方法7
this(looper, callback, false);
}
// Handler构造方法5
public Handler(boolean async) {
// 调用Handler构造方法6
this(null, async);
}
// Handler构造方法6
public Handler(Callback callback, boolean async) {
...
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;
}
// Handler构造方法7
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
// sendMessage方法
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
// 获取Looper中的队列
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
// 将消息压入Looper中的队列中
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 设置消息的target变量为本Handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
复制代码
dispatchMessage方法会先判断msg.callback是否为空,判断出是该消息msg是经过post发送出的仍是 sendMessage方法发送出的,从而在对消息进行处理。Handler有众多构造方法,不过最终调用的不过就是构造方法6和7两个,这俩构造方法的区别之处就在于第一个参数,是否自定义设置Looper,若步自定义设置Looper则默认使用主线程的Looper。sendMessage方法从源码中能够看到最终是调用 sendMessageAtTime方法将消息压入Looper中的队列的,而又是在压入队列enqueueMessage方法中设置的消息msg的target变量的Handler值。源码分析
MessageQueue中的源码就不分析啦,有兴趣的小伙伴自行查看吧。再放上一张Handler、Message、Message Queue、Looper之间的逻辑图post
public final class Looper {
// sThreadLocal 是static的变量,能够先简单理解它至关于map,key是线程,value是Looper,
//那么你只要用当前的线程就能经过sThreadLocal获取当前线程所属的Looper。
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//主线程(UI线程)的Looper 单独处理,是static类型的,经过下面的方法getMainLooper()
//能够方便的获取主线程的Looper。
private static Looper sMainLooper;
//Looper 所属的线程的消息队列
final MessageQueue mQueue;
//Looper 所属的线程
final Thread mThread;
......
}
复制代码
说到ThreadLocal,不得不说下ThreadLocalMap和Thread
1.ThreadLocal类用于存储以线程为做用域的数据,线程之间数据隔离。
2.ThreadLocalMap类是ThreadLocal的静态内部类,经过操做Entry来存储数据。
3.Thread类比较经常使用,线程类内部维持一个ThreadLocalMap类实例(threadLocals)。
handler消息机制中的Looper就存储在ThreadLocal中,也正是由于Looper的建立是依赖当前线程的,一个线程只能有惟一一个Looper,因此Looper使用于存储在ThreadLocal中。ThreadLocal类会根据当前线程存储变量数据的副本,每个线程之间数据副本互不干扰,实现线程之间的数据隔离。
// ThreadLocal类:
public void set(T value) {
// 当前线程
Thread t = Thread.currentThread();
// 获取当前线程的ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
// 返回当前线程的ThreadLocalMap
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
// Looper类
// Looper初始化时会调用该方法,上面Handler机制Hanlder部分提到过
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 将Looper设置到ThreadLocal中
sThreadLocal.set(new Looper(quitAllowed));
}
复制代码
Looper类中的prepare方法,再结合ThreadLocal类中的set方法,能够看出Looper实例是绑定到线程内部的ThreadLocalMap成员变量中的,所以一个线程只能绑定一个Looper,并且因为每一个Thread都会维护一个ThreadLocal.ThreadLocalMap类,所以这就隔绝了多线程间通信混乱的问题,保证了绝对线程安全。 若Thread中的ThreadLocalMap为空,则在set方法中会create建立。
此时就延申到了ThreadLocal的用处啦,简单说一下:当某些数据是以线程为做用域而且不一样线程具备不一样的数据副本的时候,就能够考虑采用ThreadLocal。如今来张Thread、ThreadLocalMap和 ThreadLocal关系图:
参考文章:
...
注:如有什么地方阐述有误,敬请指正。