android开发中,在子线程中进行一些操作完成后会通过handler发送一些数据给主线程。 生产者-消费者模型:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加数据, 消费者从存储空间中取走数据。跨线程的核心就是共享内存。
handler整体流程
image.png子线程 - 将消息插入队列的节点
handler -> sendMessage -> enqueueMessage -> messasgeQueue.enqueueMessage
主线程 - 将消息从队列里面取出分发
looper.loop() -> messasgeQueue.next() -> handler.dispatchMessage() -> handler.handleMessage()
image.png一、Handler的创建是与Looper创建的线程是相同的。
二、Looper中内部维护了一个MessageQueue(也就是消息队列)。且该队列是通过链表的形式实现优先级队列。
三、Hanlder最终通过sendMessage方法将消息发送到Looper中对应的MessageQueue中。
四、Looper通过消息循环获取消息后,会调用对应的消息中的target(target对应的是发消息的Handler)的dispatchMessage()方法来处理消息。
Looper原理
class ActivityThread {
public static void main(String[] args) {
...
//准备主线程looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//启动 Looper 开启消息循环
Looper.loop();
...
}
}
public final class Looper {
final MessageQueue mQueue;
final Thread mThread;
//Looper内部会创建MessageQueue对象
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
//创建主线程Looper对象 判断looper是否被创建 保存主线程的looper对象
public static void prepareMainLooper() {
//false表示消息队列不能被清除
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//当前Looper对象已经与主线程关联了
sMainLooper = myLooper();
}
}
//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对象,放入主线程局部变量中
}
//获取当前主线程的Looper对象
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
//当前Looper对象与主线程关联后,接着会调用Looper对象中的loop()方法来开启消息循环
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
//...省略部分代码
for (;;) {//一直循环去获取消息队列中的消息
Message msg = queue.next(); //该方法可能堵塞,
if (msg == null) {
//如果没有消息,表示当前消息队列已经退出
return;
}
//...省略部分代码
try {
//获取消息后,执行发送消息的handler的dispatchMessage方法。
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//...省略部分代码
}
msg.recycleUnchecked();
}
//quitSafely相比于quit方法安全之处在于清空消息之前会派发所有的非延迟消息。无论是调用了quit方法还是quitSafely方法只会,Looper就不再接收新的消息
public void quit() {
mQueue.quit(false);
}
public void quitSafely() {
mQueue.quit(true);
}
}
MessageQueue 原理 - 入队出队
class MessageQueue{
void quit(boolean safe) {
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
// 清空消息之前会派发所有的非延迟消息
removeAllFutureMessagesLocked();
} else {
//清空全部消息
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
//消息队列的加入过程
boolean enqueueMessage(Message msg, long when) {
//...省略部分代码
synchronized (this) {
//...省略部分代码
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//...省略部分代码
//循环遍历消息队列,把当前进入的消息放入合适的位置(比较等待时间)
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//将消息插入合适的位置
msg.next = p;
prev.next = msg;
}
//...省略部分代码
}
return true;
}
//MessageQueue中去获取消息,直到获取消息后才会退出
Message next() {
//...省略部分代码
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);//睡眠
synchronized (this) {
//...省略部分代码
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// 同步屏障,类似于救护车需要优先通过执行,比如更新UI,先发送同步屏障,然后再发送同步消息,循环所有消息,发现有同步消息并且是更新UI 马上出来 Async 表示刷新UI消息
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
//对比消息执行时间是不是大于当前时间
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); //计算下次执行时间
} else {
//遍历消息列表,取出消息
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
}
//...省略部分代码
}else {
// No more messages.
nextPollTimeoutMillis = -1; //没有消息就一直睡眠
}
//
if (mQuitting) {
dispose();
return null;
}
}
}
}
Handler的原理
public class Handler {
//不带Looper的构造函数,是通过Looper.myLooper()来获取当前主线程的Looper对象
public Handler() {this(null, false);}
public Handler(boolean async) {this(null, async);}
public Handler(Callback callback) {this(callback, false);}
public Handler(boolean async) {this(null, async);}
public Handler(Callback callback, boolean async) {
//Looper.myLooper()内部会调用sThreadLocal.get(),获取线程中保存的looper局部变量
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//获取当前Looper中的MessageQueue
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//带Looper参数的构造函数是线程已经通过Looper.prepare()与Looper.loop()构建了自己的循环消息队列, 只有调用了该方法后,才会将当前Looper对象放入线程的局部变量中**可以构建自己的消息处理循环,比如HandlerThread
public Handler(Looper looper) { this(looper, null, false); }
public Handler(Looper looper, Callback callback) { this(looper, callback, false);}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
//获取当前Looper中的MessageQueue
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//handler发送到MessaageQueue(消息队列)中去
//发送及时消息
public final boolean sendMessage(Message msg)
public final boolean sendEmptyMessage(int what)
public final boolean post(Runnable r)
//发送延时消息
public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
public final boolean sendMessageDelayed(Message msg, long delayMillis)
public final boolean postDelayed(Runnable r, long delayMillis)
//发送定时消息
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
public final boolean postAtTime(Runnable r, long uptimeMillis)
//所有发送的消息最后都会调用到enqueueMessage
private boolean enqueueMessage(MessageQueue queue,Message msg,long uptimeMillis) {
//handler 赋值给msg的变量中,最后分发的时候取出该handler进行分发
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
return queue.enqueueMessage(msg, uptimeMillis);
}
//Looper会调用loop()方法循环的取消息。当取出消息后会调用message.target.dispatchMessage(msg)方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//第一步,判断msg.callback handler.post()系列方法的时候
handleCallback(msg);
} else {
if (mCallback != null) {
//第二步、判断Handler的callBack
if (mCallback.handleMessage(msg)) {
return;
}
}
//第三步,执行Handler的handleMessage方法
handleMessage(msg);
}
}
handler.post()系列方法的时候会调用该方法
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
private static void handleCallback(Message message) {
message.callback.run();
}
handler 问题 https://www.jianshu.com/p/f5722e1e8e6c
网友评论