Handler机制相关概念
- Handler
发送和处理消息。 - Looper
循环从消息队列取数据。 - Runnable和Message
任务和消息,任务最终也会转化成message。 - MessageQueue
消息队列,存储消息数据。
Handler机制流程及源码分析
Android开发中案例中,经常在子线程产生的数据发送到主线线程进行处理。处理流程类似于生产者-消费者,子线程(生产者)和消费者(主线程)同个时间段公用存储空间(Message)。
private static Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
//处理消息
return false;
}
});
//发送消息
mHandler.sendEmptyMessage(0);
mHandler.post(new Runnable() {
@Override
public void run() {
}
});
流程及源码分析
创建Looper
主线程创建,在主线程即UI线程ActivityThread启动时(main函数)就通过Looper.prepareMainLooper()创建了。
//frameworks\base\core\java\android\app\ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
}
//frameworks\base\core\java\android\os\Looper.java
public static void prepareMainLooper() {
prepare(false);//主线程不能quit
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
子线程创建需要调用Looper.prepare()
//frameworks\base\core\java\android\os\Looper.java
//sThreadLocal是静态且不可变的,唯一
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//创建前先判断当前线程是否不为空,不为空表示Looper已经创建,保证一个线程只有一个Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//创建Looper并保存到ThreadLocal中
sThreadLocal.set(new Looper(quitAllowed));
}
//libcore\ojluni\src\main\java\java\lang\ThreadLocal.java
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
//实际是将Looper保存到对应线程里的map,键值是sThreadLocal
map.set(this, value);
else
createMap(t, value);
}
创建MessageQueue
MessageQueue是一个消息队列,会有队列的一些操作方法。
- 新建队列
在创建Looper的时候会创建一个MessageQueue,一个线程对应一个MessageQueue。由其构造函数和本地方法nativeInit组成,nativeInit会在本地创建一个NativeMessageQueue对象。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
//和当前线程绑定
mThread = Thread.currentThread();
}
MessageQueue(boolean quitAllowed) {
//是否允许quit,主线程是flase,不允许队列销毁退出。
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
- 元素入队
boolean enqueueMessage(Message msg, long when) - 元素出队
Message next() - 删除元素
void removeMessages(Handler h, Runnable r, Object object)
void removeMessages(Handler h, int what, Object object) - 销毁队列
和创建过程一样通过本地方法nativeDestroy
Looper.loop()循环
public static void loop() {
final Looper me = myLooper();//通过sThreadLocal.get()获取刚才创建的Looper
if (me == null) {
throw new RuntimeException