跳至主要內容

Android 异步消息机制 Handler、Message、Looper

JI,XIAOYONG...大约 2 分钟

此文为鸿洋博客阅读笔记,配合原文食用口味更佳。

Android 异步消息处理机制 让你深入理解 Looper、Handler、Message 三者关系 - CSDN 博客open in new window

导图

20200429160005
20200429160005

过程分析

Looper

Looper.perpare()

Looper.perpare()方法创建Looper对象(同时创建MessageQueue对象),并与当前线程关联保存在sThreadLocal中。

public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(true));
}

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
}

Looper.loop()

Looper.loop()方法获取保存的Looper对象并由此获取到MessageQueue对象

通过for循环,不停的通过mQueue获取到msg,并调用msg.target.dispatchMessage(msg)执行 msg 对应的处理方法。

最后通过msg.recycle()回收使用完的 msg。

public static void loop() {
    final Looper me = myLooper();
    ...
    final MessageQueue queue = me.mQueue;
    ...
    for (;;) {
        Message msg = queue.next(); // might block
        ...
        msg.target.dispatchMessage(msg);
        ...
        msg.recycle();
    }
  }

Looper.myLooper()

myLooper()内部调用sThreadLocal获取已有的Looper对象

public static Looper myLooper() {
    return sThreadLocal.get();
}

Android 的 Activity 默认在 UI 线程调用了 Looper 的prepare()loop()方法

Handler

handler.sendMessage()

Handler 构造方法会获取到mLoopermQueue以及mCallback

 mLooper = Looper.myLooper();
 mQueue = mLooper.mQueue;
 mCallback = callback;  // Handler() 中此值为 null

sendMessage()方法最终会调用sendMessageAtTime()方法,在其内部调用enqueueMessage()方法,将 handler 赋予 msg.target,并将 msg 压入 mQueue 中

//enqueueMessage 方法
msg.target = this;
queue.enqueueMessage(msg, uptimeMillis);//将 handler 发送的 msg 压入到当前线程的 Looper 持有的 MessageQueue 中

handler.dispatchMessage()

Handler 的dispatchMessage()方法会在Looper.loop()中被调用

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {  //msg 自带的回调方法
            handleCallback(msg);
        } else {
            if (mCallback != null) {  //handler 指定的回调方法
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);  //handler 的 handleMessage() 方法
        }
    }

其中执行顺序是:msg.callback > mCallback > handleMessage()

handler.post()

handler.post(new Runnable())调用了getPostMessage(r)方法将 r 赋予 msg.callback

public final boolean post(Runnable r)  {
      return  sendMessageDelayed(getPostMessage(r), 0);
   }

private static Message getPostMessage(Runnable r) {
      Message m = Message.obtain();
      m.callback = r;
      return m;
  }

最后也是在sendMessageDelayed方法中调用sendMessageAtTime()方法将 msg 压入 MessageQueue 中

public final boolean sendMessageDelayed(Message msg, long delayMillis)  {
    ...
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

msg 的获取

  • Message.obtain(); 复用 MessageMessage 池中已有的对象,避免出现分配内存 推荐
  • new Message();

总结

Looper在**perfare()**方法中创建Looper及MessageQueue对象并保存在sThreadLocal中,

在**loop()**方法中通过myLooper()sThreadLocal中取出mLooper,并由此获得mQueue,在 for 循环中通过mQueue.next()获取msg,用msg.target.dispatchMessage()方法回调handler中的msg处理方法

Handler在**构造函数**中通过Looper.myLooper()获取到当前线程的Looper和MessageQueue

**sendMessage()**方法最终通过sendMessageAtTime()调用enqueueMessage()方法将msg压入到MessageQueue中。

至此将Looper 和 Handler 通过 MessageQueue 联系在一起,并共同参与处理 Message。

此外**handler.post(runnable)也是通过在post()**内部调用getPostMessage()方法将runnable赋予msg.callback,并在post()中通过sendMessageDelayed()方法调用sendMessageAtTime()方法msg压入MessageQueue

文章标题:《Android 异步消息机制 Handler、Message、Looper》
本文作者: JI,XIAOYONG
发布时间: 2018/04/01 20:08:08 UTC+8
更新时间: 2023/12/30 16:17:02 UTC+8
written by human, not by AI
本文地址: https://jixiaoyong.github.io/blog/posts/5962504e.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 许可协议。转载请注明出处!
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8