Android Handler机制源码浅析(上)
1.Handler.java
Android Handler机制源码浅析(下) :https://blog.csdn.net/XCF95319605/article/details/81088119
Handler的主要作用是消息的发送和接收(处理消息),handler内部是通过一系列的post方法和send方法来进行消息的发送,不过post方法都是通过间接调用send方法来完成的。
Handler中的post方法列表
- post(Runnable r)
- postAtTime(Runnable r, long uptimeMillis)
- postAtTime(Runnable r, Object token, long uptimeMillis)
- postDelayed(Runnable r, long delayMillis)
- postAtFrontOfQueue(Runnable r)
Handler中send方法列表
- sendMessage(Message msg)
- sendEmptyMessage(int what)
- sendEmptyMessageDelayed(int what, long delayMillis)
- sendEmptyMessageAtTime(int what, long uptimeMillis)
- sendMessageDelayed(Message msg, long delayMillis)
- sendMessageAtTime(Message msg, long uptimeMillis)
- sendMessageAtFrontOfQueue(Message msg)
- sendMonitorMessage(Message msg, long delayMillis, long executiontimeout, long pendingtimeout, String msgLoggerName)
(1) 随便找一个post方法和send方法来进行分析,我们先来看看post方法:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
在这里我们发现post方法被调用以后就直接调用了send方法中的sendMessageDelayed方法来进行消息的发送,其他post方法也是类似的,只是传入的参数和调用了不同的send方法而已,有兴趣可以去看源码。
接下来看一下sendMessageAtTime,因为sendMessage会间接调用到这个方法,所以就对这个方法进行分析:
public boolean sendMessageAtTime(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); //调用enqueueMessage方法
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis); //将msg方法消息队列中
}
其实我们平时是调用sendMessage方法,但是sendMessage会直接调用sendMessageDelayed方法,而sendMessageDelayed又会直接调用到sendMessageAtTime方法,所以就忽略掉前面部分,直接从sendMessageAtTime开始分析,首先sendMessageAtTime被调用时,会先获取到当前的MessageQueue,进行判空,然后调用enqueueMessage方法,enqueueMessage最后将消息插入到消息队列,至此完成了一次简单的Message的发送流程。
(2) 接下来我们来分析一下Handler处理消息的过程:
handler是通过dispatchMessage方法来处理消息的,而dispatchMessage方法是被在Looper中被调用的,我们首先来看一下dispatchMessage的源码实现,然后再去分析Looper中对dispatchMessage的调用,Handler中dispatchMessage源码实现:
public void dispatchMessage (Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
dispatchMessage的源码很简单,第一步:先检查msg的callback(Runnable)是否为空,若不为空,则交给handlerCallback处理,我们来看看handlerCallback源码做了什么:
private static void handleCallback(Message message) {
message.callback.run();
}
handlerCallback的源码也很简单,就是开启传进来的message的run方法,那么问题来了,为什么有run方法,相信从前面的post方法你已经看出来了,这个run方法就是前面通过post发送消息时传递进来的那个Runnable实现类的run方法,好了,第一个if语句已经剖析清楚了。
接下来我们看看第二个if语句,检查mCallback是否为空,不为空则将消息交给handlerMessage来处理,首先我们来看看mCallback在源码中的定义:
final Callback mCallback; //Callback类
我们再看看Callback的定义:
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
那么这个mCallback又是在哪初始化的呢?还是看源码:
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Callback callback, boolean async) {
…
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
原来是当我们采用传入一个callback来获取一个handler实例的时候,重写里面的handleMessage来处理具体的消息,在Callback的接口的上面注释以及说明了:在实例化处理程序时可以使用的回调接口,以避免实现自己的Handler子类。
最后程序将会把消息交给我们重写的handleMessage来进行处理,至此,整个Handler的消息处理过程分析完毕。
2.Looper.java
Looper在Android消息机制中就专门负责循环的去监听消息,监听哪儿的消息呢?对就是MessageQueue里面的消息,当MessageQueue里面有消息的时候Looper就会去将消息取出来给Handler进行处理,首先我们来分析一下Looper 的构造方法:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
很简单,构造方法就做了两件事,首先是创建一个消息队列,然后将当前Looper所在的线程进行了保存操作。
Handler正常工作是离不开Looper的,那么为什么我们平时在UI线程使用Handler的时候却没有手动的去创建Looper呢?那是因为Android系统默认帮我们在主线程创建了一个Looper所以并不需要我们去手动的创建Looper对象,以下源码是在ActivityThread中的main方法中,Android系统为我们创建Looper的过程,已经删减掉和Looper无关的代码:
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
接下来我们来分析一下UI线程获取到Looper的过程,在main方法中首先调用了Looper的prepareMainLooper()方法,该方法是用来实例化Looper对象的,跟着源码的调用轨迹来看一下调用过程:
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();//调用myLooper()获取Looper对象
}
}
返回与当前线程相关联的Looper对象,如果调用线程没有与Looper关联,则返回null。
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
最后调用Looper.loop();来开启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;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
final long end;
try {
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (slowDispatchThresholdMs > 0) {
final long time = end - start;
if (time > slowDispatchThresholdMs) {
Slog.w(TAG, "Dispatch took " + time + "ms on "
+ Thread.currentThread().getName() + ", h=" +
msg.target + " cb=" + msg.callback + " msg=" + msg.what);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
loop方法里面最重要的地方就是for(;;)代码块,里面是一个死循环,而跳出该循环的唯一条件是msg为空,就是当MessageQueue的next方法返回了null。如果next方法返回了新的消息,looper就会处理这条消息:msg.target.dispatchMessage(msg);,这里的msg.target指的是发送这条消息的对象,这样,相当于消息最后又回到了Handler本身去处理消息。至此整个Looper的工作流程就基本分析完毕了,就是通过Looper的构造器创建一个消息队列,然后通过prepareMainLooper在当前线程实例化Looper对象,最后通过loop方法来开启循环,处理相应的消息,只是所谓的处理是把消息对象返回给发送这条消息的Handler对象。
Looper除了提供prepareMainLooper让UI线程实例化Looper以外,还提供了prepare()方法来方便我们在任意线程实例化Looper对象,使用方式可参考上面main方法中,都是先通过prepare()来实例化对象,然后通过loop()方法来开启循环。
至此,整个Looper的循环处理过程就分析完毕了。
Android Handler机制源码浅析(下) :https://blog.csdn.net/XCF95319605/article/details/81088119
上一篇: (3)搜索二维矩阵 II