一、Handler
1、工作原理:
Handler发送消息是往消息队列MessageQueue中插入一条消息,轮询器Looper会调用loop方法进行轮询,获取到消息后将该消息交给Handler处理。
2、发送消息(调用send和post的相关方法发送消息)
调用sendMessage,然后调用sendMessageDelayed,又调用了sendMessageAtTime。调用post方法,最终也是调用sendMessageAtTime方法。
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);
}
会调用MessageQueue的enqueueMessage方法将消息放到消息队列中。Looper发现新消息,会处理。
3、接收消息
#Handler
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);//是一个Runnable对象,实际是Handler的post传递的Runnable参数
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
4、Handler实例化
通过特定的Looper来构造Handler
public Handler(Looper looper) {
this(looper, null, false);
}
二、Looper:不停的从消息队列MessageQueue中查看是否有新消息。
1、创建Looper。每个线程最多只能有一个Looper对象。
(1)Looper.prepare();
#Looper
public static void prepare() {
prepare(true);
}
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));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);//创建一个MessageQueue.
mThread = Thread.currentThread();
}
(2)
Looper.prepareMainLooper:主线程创建Looper,本质也是通过prepare方法创建
2、获取Looper
(1)Looper.getMainLooper 获取主线程的Looper
(2)Looper.myLooper()获取当前线程的Looper实例
3、退出Looper
#Looper
(1)直接退出Looper
public void quit() {
mQueue.quit(false);
}
(2)设置一个退出标识,将消息队列的已有消息处理完毕才能安全退出。
public void quitSafely() {
mQueue.quit(true);
}
会调用MessageQueue的quit方法通知消息队列退出,MessageQueue的next方法返回null。
退出后Handler发送的消息会失败。在子线程中创建Looper,在所有消息完成后调用quit方法来终止消息循环。
4、进行轮询
4、进行轮询
Looper.looper
public static void loop() {
.....
//无限循环
for (;;) {
//调用MessageQueue的next方法取值
Message msg = queue.next();
if (msg == null) {
//木有消息了就跳出循环
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
//msg.target指发送消息的Handler,交给Handler的dispatchMessage方法
msg.target.dispatchMessage(msg);
.....
}
}
5、数据存取
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
通过
ThreadLocal可以实现Looper在线程的数据存取。
原理: Looper作用域是线程,不用线程有不用的Looper。而ThreadLocal是一个线程内部的数据存储类。可在指定线程存储数据,其他线程无法获取。
(1)ThreadLocal使用:
ThreadLocal<Boolean> mThreadLocal = new ThreadLocal<>();
public void test() {
Log.e(TAG, "mainThread:" + mThreadLocal.get()); //主线程 结果是false
new Thread() {
@Override
public void run() {
super.run();
mThreadLocal.set(false);
Log.e(TAG, "thread1:" + mThreadLocal.get()); //线程1 结果是false
}
}.start();
new Thread() {
@Override
public void run() {
super.run();
mThreadLocal.set(true);
Log.e(TAG, "thread2:" + mThreadLocal.get()); //线程2 结果是true
}
}.start();
}
(2)
ThreadLocal的set方法:
public void set(T value) {
Thread currentThread = Thread.currentThread();//获取当前线程
Values values = values(currentThread); //Value的类型是ThreadLocal.Value
if (values == null) { //value为null,进行初始化
values = initializeValues(currentThread);
}
values.put(this, value); //调用value的put方法存值
}
//内部存在obect类型的数组
static class Values {
private Object[] table;
}
(3)
ThreadLocal的get方法:
public T get() {
// Optimized for the fast path.
Thread currentThread = Thread.currentThread();
Values values = values(currentThread); //获取当前线程value对象
if (values != null) {
Object[] table = values.table; //取出value的table数组
int index = hash & values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1]; //table的下一个位置存得值就是ThreadLocal的值
}
} else {
values = initializeValues(currentThread); //初始化
}
return (T) values.getAfterMiss(this);
}
set和get都是操作的当前线程的value对象的table数组。
三、MessageQueue:
内部以单链表的形式存储数据,包含两个操作,插入enqueueMessage方法和读取next方法。
next是一个无限循环的方法,如果没消息就一直堵塞。如果有新消息到来,从消息队列中取出一条数据,并将其在队列中移除。
四、主线程的消息循环
1、主线程的入口是ActivityThread的main方法
public static void main(String[] args) {
.....
//创建主线程的Looper和MessageQueue
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
//获取handler
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进行轮询
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
返回的Handler是ActivityThread.H。包含了四大组件启动和停止的过程。
private class H extends Handler {}
主线程的消息循环模型:
(1)ActivityThread通过内部类ApplicationThread和ActivityManagerService进行进程间通信
(2)AMS会回调ApplicationThread的Binder方法
(3)ApplicationThread向H发送消息
(4)ApplicationThread将通过H将逻辑切换到ActivityThread中执行(主线程执行)
注意:
- 一个Looper只能对应了一个MessageQueue。
- 一个线程中只有一个Looper实例,一个MessageQueue实例,
- 可以有多个Handler实例。
参考:Android开发艺术探索