1.Runnable和Message可以被压入到MessageQueue中,形成一个集合。一般情况下某种类型的MessageQueue只允许保存相同类型的Object,实际源码中需要先对Runable进行相应转换。
Looper.prepare()的代码:
2.Looper循环的去从MessageQueue中取出item,然后交与Handler处理。加入消息队列为空,Looper将进入休眠。
3.Handler利用自身的处理机制,对传入的各种Object进行处理并产生最终效果。
Handler
每一个Thread只对应一个Looper;
每一个Looper只对应一个MessageQueue;
每一个MessageQueue中有N个Message;
每一个Message最多只能由一个Handler来处理。
由此,Thread和Handler是一对多的关系。
Handler的工作:
~1.处理Message,包括对Message进行分发,和对Message进行处理。
分发流程,首先判断msg.callback是否为空,在Message类中,可以知道msg.callback就是Runable,不为空优先处理,即执行run方法;其次判断Handler.mCallback是否为空,不为空时调用mCallback.handlerMessage;如果前两个对象都不存在,才调用Handler.handlerMessage
~2.将某个Message压入MessageQueue中。post系列的方法都是提供的Runnable对象,post需要先将其封装成Message,接着通过对应的send函数把它推送到MessageQueue中。这里需要注意可以将消息至于消息队列的最前端,即looper优先取出。
~3.将某个Message从MessageQueue中移除。可以移除尚未被执行的Runnable。
Looper
Looper在Android线程中使用只有三个步骤:
1.Looper的准备工作(prepare)
2.创建处理消息的Handler
3.Looper开始工作(loop)
Looper在应用程序中的使用分为两种情况
1.主线程
2.普通线程
在
ActivityThread.java
源码中的main方法里面有下面一段代码:
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
其中
Looper.prepareMainLooper()和Looper.prepare()本质上有没有区别?
Looper.prepareMainLooper()的代码:
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.prepare()的代码:
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));
}
我们可以看到都用到了prepare,参数中的false表示线程不允许退出。所以说在本质上两者是没有什么区别的。
sThreadLocal.get()是什么呢?
在Looper中有一个很重要的成员变量:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
这是一个静态类型的变量,只要import了Looper,
sThreadLocal
就会存在并构建完毕。
ThreadLocal是什么东西呢?
Implements a thread-local storage, that is, a variable for which each thread has its own value.
由此,
ThreadLocal是一中特殊的全局变量,全局性只限于自己的线程,
sThreadLocal.get()
告诉我们,每个线程的Looper都是独立的。