handler机制的源码分析和理解


这里写自定义目录标题

  • 学习handler机制
    • 1、创建线程消息队列
    • **2、线程消息的循环过程**
    • **3、线程的消息发送**
    • **4、线程消息处理过程**
【handler机制的源码分析和理解】
学习handler机制 首先举例handler的简单使用:
线程1
Runnable runnable1 = new Runnable() { @Override public void run() { Looper.prepare(); //创建Looper、MessageQueue实例化对象 handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.e("Data", "handleMessage: " + msg.obj.toString()); } }; Looper.loop(); // 进入loop循环 } };

线程2
Runnable runnable2 = new Runnable() { @Override public void run() { Message message = handler.obtainMessage(); message.obj = "你好啊,线程一"; handler.sendMessage(message); }

线程二中使用的 handler 是线程一中创建的 handler
线程一中使用的looper方法
Looper.prepare(); 将当前线程初始化为 消息线程
Looper.loop(); 在此线程中运行 消息队列
######################################################################################
在学习handler机制中我们必须了解其中主要的四个类的作用
1 、Looper 类是用来创建消息队列的。
2 、MessageQueue 类是用来描述消息队列的。
3、Message 类是用来描述发送的消息。
4、Handler 类是用来发送和接受消息。
1、创建线程消息队列 android中应用线程的消息队列MessageQueue是由Looper类调用prepareMainLooper() 或 prepare() 来创建。这两者之间的差别在于prepareMainLooper应用于主线程创建消息队列, prepare() 应用于子线程创建消息队列。
1.1 创建Looper 对象,然后在Looper对象的构造函数中创建MessageQueue的对象。
frameworks/base/core/java/android/os/Looper.java
public final class Looper { ....... static final ThreadLocal sThreadLocal = new ThreadLocal(); // 用来保存Looper的实列化对象。 final MessageQueue mQueue; //描述消息队列 private static Looper sMainLooper; // 主线程的Looper 对象 ....... private Looper(boolean quitAllowed) {// 参数判断是否允许推出,主线程不允许退出,子线程允许退出。 mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } //子线程调用创建MessagerQueue: prepare() -> prepare(boolean quitAllowed) -> Looper(boolean quitAllowed) public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) {//从类似hashmap的sThreadLocal中获得Looper的实列化对象 throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); //如果之前没有创建过,就创建一个新的Looper对象并set进去。 }// 主线程调用创建MessagerQueue:prepareMainLooper() ->prepare(boolean quitAllowed) -> Looper(boolean quitAllowed) -> myLooper() public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } }public static @Nullable Looper myLooper() { return sThreadLocal.get(); } }

1.2 引入MessageQueue,然后在MessageQueue的对象中记录C++层的NativeMessageQueue对象的地址。
frameworks/base/core/java/android/os/MessageQueue.java
// mPtr 用来记录C++层NativeMessageQueue对象的地址。 MessageQueue(boolean quitAllowed) { mQuitAllowed = quitAllowed; mPtr = nativeInit(); // 创建C++层NativeMessageQueue对象 }

1.3 返回NativeMessageQueue对象的地址
frameworks/base/core/jni/android_os_MessageQueue.cpp
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) { NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue(); if (!nativeMessageQueue) { jniThrowRuntimeException(env, "Unable to allocate native queue"); return 0; }nativeMessageQueue->incStrong(env); return reinterpret_cast(nativeMessageQueue); }

1.4 在NativeMessageQueue的构造函数中实列化Native Looper
frameworks/base/core/jni/android_os_MessageQueue.cpp
// getForThread() 用来判断是否已经创建过一个native 的 looper。 setForThread() 将new的Looper对象和当前进程绑定 NativeMessageQueue::NativeMessageQueue() : mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) { mLooper = Looper::getForThread(); if (mLooper == NULL) { mLooper = new Looper(false); Looper::setForThread(mLooper); } }

2、线程消息的循环过程 创建了Looper、MessageQueue之后,就开始进入Loop循环。
2.1 调用loop方法
frameworks/base/core/java/android/os/Looper.java
// 在loop()中我们首先会get到当前的looper的实例化对象, 之后再找到这个looper对应的messageQueue对象。调用next()进入messageQueue类 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(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } ......... }

2.2 进入MessageQueue 类
frameworks/base/core/java/android/os/MessageQueue.java
// 调用 nativePollOnce()不断的检查当前线程的消息队列中是否有新的消息需要处理。 Message next() { // Return here if the message loop has already quit and been disposed. // This can happen if the application tries to restart a looper after quit // which is not supported. final long ptr = mPtr; if (ptr == 0) { return null; }int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; // 进入睡眠的等待时间。=0 ,即使没有消息进入消息队列,也不能进入睡眠。= -1 当前没有新的消息,线程就需要无限的处于睡眠等待状态。 > 0 当前线程在没有新的消息的情况下,进入睡眠状态等待的时间。 for (; ; ) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); }nativePollOnce(ptr, nextPollTimeoutMillis); .......... } ........... }

**2.3 从next() -> nativePollOnce()
frameworks/base/core/jni/android_os_MessageQueue.cpp
**
其实在这里直接就是从nativePollOnce() -> pollOnce()
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, jlong ptr, jint timeoutMillis) { NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); nativeMessageQueue->pollOnce(env, obj, timeoutMillis); }

而在 pollOnce()又会调到 native looper的 pollOnce
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) { mPollEnv = env; mPollObj = pollObj; mLooper->pollOnce(timeoutMillis); mPollObj = NULL; mPollEnv = NULL; if (mExceptionObj) { env->Throw(mExceptionObj); env->DeleteLocalRef(mExceptionObj); mExceptionObj = NULL; } }

2.4 从nativeMessageQueue::pollOnce -> Looper::pollOnce()
system/core/libutils/Looper.cpp
这里由于Looper::pollOnce()的代码理解难度有点大,我们这就顺带提一下它的作用有兴趣的可以查看文章 https://www.jianshu.com/p/4fac27284475
Looper::pollOnce() 的作用就是睡眠与唤醒的线程的作用。
3、线程的消息发送 3.1 Handler主要就是用来向一个线程的消息队列发送消息
frameworks/base/core/java/android/os/Handler.java
public Handler(Callback callback, boolean async) { .......... mLooper = Looper.myLooper(); mQueue = mLooper.mQueue; mCallback = callback; ......... } public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public void handlerMessage(Message msg) { }

这里我们可以看到一个Handler类中有Looper 、MessageQueue成员变量。Handler 对象使用成员函数sendMessage() 向成员变量mQueue 发送消息。而成员函数handlerMessage()用来接收处理消息,他是与mLooper所关联的线程中调用的。
3.2 我们先从sendMessage() 发送一个消息开始
frameworks/base/core/java/android/os/Handler.java
从sendMessage()最后会调到sendMessageAtTime() 然后又到MesssageQueue的enqueueMessage()
这里的参数 msg 描述的是即将发送的消息,uptimeMillis则是用来描述发送的消息需要处理的时间。
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }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); }private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; // 将当前正在处理的一个Handler 对象。赋值给target if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }

3.3 在MessageQueue中equeueMessage会对要发送的消息msg进行处理,会根据这个消息需要处理的等待时间将msg插入到合适的位置。这里不是直接的放入到messageQueue 中而是插入到Message的next指针后面
boolean enqueueMessage(Message msg, long when) { ....... msg.markInUse(); msg.when = when; //msg中记录等待的处理时间 Message p = mMessages; //当前的消息 boolean needWake; // 是否需要唤醒线程处理消息 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 { // Inserted within the middle of the queue.Usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. 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; } // 调到native 从 nativeWake()-> wake() static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) { NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); nativeMessageQueue->wake(); }

**3.4 最后从NativeMessageQueue又会调到Looper的wake()
system/core/libutils/Looper.cpp
**
void Looper::wake() { #if DEBUG_POLL_AND_WAKE ALOGD("%p ~ wake", this); #endifuint64_t inc = 1; ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t))); // 这里会通过管道文件描述符mWakeEventFd,向管道写一个新的数据,线程就被唤醒了。 if (nWrite != sizeof(uint64_t)) { if (errno != EAGAIN) { LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s", mWakeEventFd, strerror(errno)); } } }

至此一个消息如何发送,如何插入到消息队列,之后唤醒线程就结束了,后面再继续分析如果接收处理一个消息。
4、线程消息处理过程 **4.1 **
持续更新。。。。。。

    推荐阅读