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<Looper> sThreadLocal = new ThreadLocal<Looper>(); // 用来保存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<jlong>(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<NativeMessageQueue*>(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<NativeMessageQueue*>(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);
#endif

    uint64_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 **
持续更新。。。。。。

发布了14 篇原创文章 · 获赞 4 · 访问量 3513

猜你喜欢

转载自blog.csdn.net/lisiwei1994/article/details/102505034