一.Handler 运行原理图
二.创建
1.主线程中创建
一般在 Activity
中这样创建 Handler
,其实当前的 Handler
获取的 Looper
是在 ActivityThread 中创建的。
Handler handler = new Handler();//Looper 是在ActivityThread 中创建的
ActivityThread
源码,ActivityThread
并不是一个 Thread
,它只是叫 ActivityThread
来表示它是 Activity
的开始类。
//ActivityThread.java
final H mH = new H();//真正来处理 Message 信息
final Looper mLooper = Looper.myLooper();//当ActivityThread创建的时候,就获得了 Looper
public static void main(String[] args) {
//...code
Looper.prepareMainLooper();//开启 Looper 的主循环 sThreadLocal.set(new Looper(quitAllowed));
//...code
ActivityThread thread = new ActivityThread();
//...code
Looper.loop();//开启循环
}
2.子线程中创建
如果在其他线程想要开启一个 handler ,下面的代码直接运行的话,就会报错。
//handler 在子线程中创建
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Handler handler = new Handler();
}
});
报错提示:如果要在其他线程创建就必须调用 Looper.prepare()
和 Looper.loop()
Looper.prepare()
在当前线程创建Looper 对象Looper.loop()
开启循环,保证此线程一直存活
//handler 在子线程中创建
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler();
Looper.loop();
}
});
3.Looper分析
3.1). Looper.perpare()
public static void prepare() {
prepare(true);//创建一个可以退出的 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 对象
}
3.2). Looper.loop()
public static void loop() {
final Looper me = myLooper();//通过 sThreadLocal.get();得到具体的Looper
if (me == null) {
//如果 looper 为空 ,那么直接报错
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();//清除Binder中的调用 sid,并获取当前的 pid, 让IPCThread 知道 pid
final long ident = Binder.clearCallingIdentity();//清除Binder中的调用 sid,并获取当前的 pid, 让IPCThread 知道 pid
//...
for (;;) {
Message msg = queue.next(); // 取出消息,可能会中断
if (msg == null) {
//没有消息,则退出循环
return;
}
//...
try {
msg.target.dispatchMessage(msg);//真正执行 Runnable()中的 run() 或者 handleMessage()
//执行 和 msg 相关联 handler 的 dispatchMessage() 方法
//请看下面的代码分析
} catch (Exception exception) {
} finally {
}
//...
final long newIdent = Binder.clearCallingIdentity();//清除Binder中的调用 sid,并获取当前的 pid, 让IPCThread 知道 pid
//...
msg.recycleUnchecked();//消息回收
}
}
msg.target.dispatchMessage(msg)
源码分析
我们看Message
类,里面保存了当前绑定的 Handler
、Runnable
、nextMessage
等重要的元素。
//Message.java
public final class Message implements Parcelable {
/*package*/ Handler target;//关联的具体的 Handler 对象
/*package*/ Runnable callback;//如果使用的 post(Runnable r); 方法的都会吧 Runable
/*package*/ android.os.Message next;//单链表,指向下一个消息
}
我们从 post()
方法看
//Handler.java
//发送消息
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
//把具体的 Runnable 绑定到 Message.callback 上
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
//Handler.java
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
//
handleCallback(msg);//执行绑定的 Runnable callback
} else {
if (mCallback != null) {
// Handler 构造方法传入 public Handler(Callback callback, boolean async);
if (mCallback.handleMessage(msg)) {
//
return;
}
}
handleMessage(msg);//执行 Handler 的 handleMessage()方法
}
}
3.3).MessageQueue.next()
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//...
for (;;) {
//...
nativePollOnce(ptr, nextPollTimeoutMillis);//没有任务就挂起 nextPollTimeoutMillis:-1 表示永久阻塞
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
//取出异步消息
//被障碍物挡住了。查找队列中的第一个异步消息。
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
//如果为isAsynchronous()=true :while(true&&false)=> false 已经获取到异步消息
//如果为isAsynchronous()=false :while(true&&true) => true 继续循环获取异步消息
//总结:先会执行异步消息,然后才执行正常消息。
}
if (msg != null) {
if (now < msg.when) {
//时间点内没有任务,计算下次要执行的之间
nextPollTimeoutMillis =