Handler机制相关流程
作者:互联网
Handler:发送和接收消息
Looper :轮询循环消息队列,一个线程只有一个Looper
Message:消息的实体
MessageQueue:主要是存储消息和管理消息
创建Looper:
//ActivityThread.java
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
//此处省略代码
Looper.prepareMainLooper();//初始化Looper和messagQueue
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();//用于循环消息
throw new RuntimeException("Main thread loop unexpectedly exited");
}
//Looper.java
public static void prepareMainLooper() {
//消息队列不可以quit
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
/**
prepare有两个重载的方法,主要是看prepare(boolean quitAllowed) 作用是在创建出MessageQueue时后标识消息队列是否可以被销毁,
但是在主线程中时不会被销毁的
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//quitAllowed
//sThreadLocal.get()不为空表示已经创建出Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
//每个线程只能创建出一个Looper
}
//这个地方就是创建出Looper,并且存放到sThreadLocal中
sThreadLocal.set(new Looper(quitAllowed));
}
MessageQueue创建以及如何绑定Looper
private Looper(boolean quitAllowed) {
//创建MessageQueue
mQueue = new MessageQueue(quitAllowed);
//与当前的线程进行绑定
mThread = Thread.currentThread();
}
MessageQueue(boolean quitAllowed) {
//quitAllowed表示是队列是否可以被销毁,主线程的队列不可以被销毁需要传入false
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
Looper.looop()
public static void loop() {
final Looper me = myLooper();//从sThreadLocal中获取到创建出的looper对象
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
boolean slowDeliveryDetected = false;
for (;;) {
//死循环表示会一直去查询消息
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
// 队列里面没有消息,需要等待MessageQueue发送消息
return;
}
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
try {
//查询到消息后,然后会去回调到Handler中的dispatchMessage中
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//后面代码省略......
}
创建handler
//常见的Hanlder的创建方式
Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
public Handler(@Nullable Callback callback, boolean async) {
//获取Looper,这个是从sThreadLocal中获取到的
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//创建出消息队列MessageQueue
mQueue = mLooper.mQueue;
//初始化回调
mCallback = callback;
mAsynchronous = async;
}
Looper.myLooper()
Looper.java
//主要是处理多线程并发的问题
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//获取对于的Looper对象,必须先要调用prepare()方法进行创建
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
创建Message
Message.java
1. Message message = new Message();
2. Message obtain = Message.obtain();
//使用Message.obtain比直接new出来的Message要好,可以避免多次创建,销毁message对象优化内存和性能的目的
public static Message obtain() {
//用来同步,保证线程安全
synchronized (sPoolSync) {
//回收和复用Handler
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
Message与Handler的绑定
创建Message的时候可以通过Message.obtain(Handler h)这个构造函数去绑定,也可以在Handler enqueueMessage中去绑定,所有发送的Message消息都会调用此方法入队,所以在创建Message的时候可以不去绑定。
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;//绑定
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Handler发送消息
Handler发送的消息重载方法很多,但常用的只有两种。sendMessage(Message)方法通过一系列的重载方法调用如下流程:
//1.入口
handler.sendMessage(Message);
//调用到sendMessage
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
//2.调用sendMessageDelayed
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
//3.调用到sendMessageAtTime
public boolean sendMessageAtTime(@NonNull 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);
}
//4.调用到enqueueMessage
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
//5.调用到enqueueMessage
//将消息保存在消息队列中,最终又Looper取出,交给Handler的dispatchMessage进行处理
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//表示此消息队列已经被放弃了
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
//延迟时间
msg.when = when;
//获取到消息的第一个元素
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
//如果此队列中头部元素是null(空的队列,一般是第一次),或者此消息不是延时的消息,则此消息需要被立即处理,
//此时会将这个消息作为新的头部元素,然后判断如果Looper获取消息的线程如果是阻塞状态则唤醒它,让它立刻去拿消息处理
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//如果此消息是延时的消息,则将其添加到队列中,原理就是链表的添加新元素,按照when,也就是延迟的时间来插入的,延迟的时间越长,
//越靠后,这样就得到一条有序的延时消息链表,取出消息的时候,延迟时间越小的,就被先获取了.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {//唤醒线程
nativeWake(mPtr);
}
}
return true;
}
public void dispatchMessage(@NonNull Message msg) {
//callback在Message的构造方法中初始化和使用
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
//最终回调到上层执行handlerMessage方法
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
Handler处理消息
在handlerMessage(Message)方法中,我们就可以拿到Message对象,然后进行处理,整个Handler的流程就结束了
Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
//获取Message,进行处理
super.handleMessage(msg);
}
};
总结
Handler的大致流程如上步骤。 从handler.sendMassge发送消息到消息队列MessageQueue,然后调用looper调用到自己loop()函数带动MessageQueue从而去轮询MessageQueue里面的每个Message,当Message达到了可以执行的时间的时候开始执行,执行后会调用Message绑定的Handler来处理消息。
标签:MessageQueue,流程,Handler,Looper,msg,new,Message,机制 来源: https://blog.csdn.net/qq_42989195/article/details/123191045