Android 消息机制原理 (源代码分析)

来源:互联网 发布:ubuntu磁盘空间查看 编辑:程序博客网 时间:2024/09/21 06:38

Android 消息机制原理 (源代码分析)

  • 示例
  • 基本工作原理
  • 应用进程入口函数
  • 创建主循环器
  • 发送消息
  • 循环获取需要处理的消息,并进行处理
  • 消息对象的回收与复用

示例

在主线程运行以下代码,等待一秒后,handler.handleMessage(myMsg) 将在主线程中被执行:

Handler handler = new Handler() {    @Override    public void handleMessage(Message msg) {        ...    }}new Thread() {    @Override    public voide run() {        Message myMsg = new Message();        handler.sendMessageDelayed(myMsg, 1000L);    }}.start();

基本工作原理

每个循环器(Looper 对象)内部有一个消息队列(MessageQueue 对象),负责维护当前循环器的待处理消息(Message 对象)链表,每个待处理消息按处理时间的先后顺序链接。

Handler 对象创建时会自动关联到当前线程已经创建的循环器,每个线程最多只可以创建一个循环器,当在子线程中通过前面创建的 Handler 对象发送消息时,消息就会被添加到 Handler 对象关联的循环器内部的待处理消息链表里。

创建循环器后调用 Looper.loop() 不断轮询待处理消息链表,获取当前需要处理的消息,并处理消息,Android 环境在应用启动时已经在主线程执行了这些步骤。

应用进程入口函数

AOSP:

应用进程启动时,进程入口函数 ActivityThread.main(...) 在主线程 (又称 UI 线程) 中被执行:

// AOSP(Android Open Source Project) 源代码所在文件: frameworks/base/core/java/android/app/ActivityThread.javapublic static void main(String[] args) {    ...    // 创建主循环器    Looper.prepareMainLooper();    ...    // 不断循环阻塞等待获取需要处理的消息,并进行处理    Looper.loop();    ...}

创建主循环器

Looper.prepareMainLooper() 主要负责创建在当前线程(即主线程)创建一个循环器,作为应用的主循环器:

// AOSP: frameworks/base/core/java/android/os/Looper.java// 用于存放在不同线程中创建的循环器static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();// 主循环器private static Looper sMainLooper;// 在当前线程创建一个循环器private static void prepare(boolean quitAllowed) {    // 每个线程只允许有一个循环器    if (sThreadLocal.get() != null) {        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}// 获取在当前线程创建的循环器public static @Nullable Looper myLooper() {    return sThreadLocal.get();}public static void prepareMainLooper() {    prepare(false);    synchronized (Looper.class) {        if (sMainLooper != null) {            throw new IllegalStateException("The main Looper has already been prepared.");        }        sMainLooper = myLooper();    }}

初始化循环器,在内部创建一个消息队列:

// AOSP: frameworks/base/core/java/android/os/Looper.javafinal MessageQueue mQueue;final Thread mThread;private Looper(boolean quitAllowed) {    // 创建消息队列    mQueue = new MessageQueue(quitAllowed);    mThread = Thread.currentThread();}

发送消息

初始化 Handler 对象,引用在当前线程创建的循环器,和它内部的消息队列:

// AOSP: frameworks/base/core/java/android/os/Handler.javafinal Looper mLooper;final MessageQueue mQueue;final Callback mCallback;final boolean mAsynchronous;public Handler() {    this(null, 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;}

Handler.post...(...)Handler.send...(...)Handler.sendMessageAtFrontOfQueue(...) 都是负责发送消息,它们最终调用 Handler.enqueueMessage(...) 将消息交给初始化时关联的消息队列:

// AOSP: frameworks/base/core/java/android/os/Handler.javapublic boolean sendMessageAtTime(Message msg, long uptimeMillis) {    MessageQueue queue = mQueue;    if (queue == null) {        ...        return false;    }    return enqueueMessage(queue, msg, uptimeMillis);}public final boolean sendMessageAtFrontOfQueue(Message msg) {    MessageQueue queue = mQueue;    if (queue == null) {        ...        return false;    }    return enqueueMessage(queue, msg, 0);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {    // 负责处理消息的 Handler 对象    msg.target = this;    if (mAsynchronous) {        msg.setAsynchronous(true);    }    return queue.enqueueMessage(msg, uptimeMillis);}

MessageQueue.enqueueMessage(...) 将消息插入到有序的待处理消息链表中:

// AOSP: frameworks/base/core/java/android/os/MessageQueue.java// 待处理消息链表头Message mMessages;// 保存到链表时,指向下一个消息对象Message next;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) {        ...        msg.markInUse();        msg.when = when;        Message p = mMessages;        ...        // 如果 when 为 0 插入到链表头,否则按 when 属性从小到大插入到链表,        // 如果遇到相同,再按从先进到后进插入到链表        if (p == null || when == 0 || when < p.when) {            msg.next = p;            mMessages = msg;            ...        } else {            ...            Message prev;            for (;;) {                prev = p;                p = p.next;                if (p == null || when < p.when) {                    break;                }                ...            }            msg.next = p; // invariant: p == prev.next            prev.next = msg;        }        ...    }    return true;}

循环获取需要处理的消息,并进行处理

Looper.loop() 负责不断循环调用 MessageQueue.next() 获取需要处理的消息,并调用 Handler.dispatchMessage(...) 处理消息:

// AOSP: frameworks/base/core/java/android/os/Looper.javapublic 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();        if (msg == null) {            // No message indicates that the message queue is quitting.            return;        }        ...        // 处理消息        msg.target.dispatchMessage(msg);        ...        // 回收消息对象        msg.recycleUnchecked();    }}

MessageQueue.next() 阻塞等待,返回待处理消息链表中靠前那个当前需要处理的消息:

// AOSP: frameworks/base/core/java/android/os/MessageQueue.javaMessage next() {    ...    int nextPollTimeoutMillis = 0;    for (;;) {        ...        // TODO: 有待继续分析        // 进程挂起 nextPollTimeoutMillis 毫秒,若链表发生变化则提前唤醒(见底层 epoll 函数)        nativePollOnce(ptr, nextPollTimeoutMillis);        synchronized (this) {            // 获取自开机以来经过的毫秒数            final long now = SystemClock.uptimeMillis();            Message prevMsg = null;            Message msg = mMessages;            if (msg != null && msg.target == null) {                // TODO: 有待继续分析                // 跳过障碍,寻找下一个异步消息                do {                    prevMsg = msg;                    msg = msg.next;                } while (msg != null && !msg.isAsynchronous());            }            if (msg != null) {                if (now < msg.when) {                    // 计算这个消息需要等待的时间                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);                } else {                    // 时间已到,将消息从待处理消息链表删除并返回                    mBlocked = false;                    if (prevMsg != null) {                        prevMsg.next = msg.next;                    } else {                        mMessages = msg.next;                    }                    msg.next = null;                    ...                    msg.markInUse();                    return msg;                }            } else {                nextPollTimeoutMillis = -1;            }            ...        }        ...    }}

Handler.dispatchMessage(...) 处理消息:

// AOSP: frameworks/base/core/java/android/os/Handler.java// 子类需覆盖本方法用来接收消息public void handleMessage(Message msg) {}public void dispatchMessage(Message msg) {    if (msg.callback != null) {        handleCallback(msg);    } else {        if (mCallback != null) {            if (mCallback.handleMessage(msg)) {                return;            }        }        handleMessage(msg);    }}

消息对象的回收与复用

Message.recycleUnchecked() 负责将自己放入缓存池留待复用:

// AOSP: frameworks/base/core/java/android/os/Message.javaprivate static final Object sPoolSync = new Object();// 共享缓存池的链表头private static Message sPool;// 当前共享缓存池大小private static int sPoolSize = 0;// 共享缓存池大小上限private static final int MAX_POOL_SIZE = 50;// 保存到链表时,指向下一个消息对象Message next;void recycleUnchecked() {    // 清除所有属性    flags = FLAG_IN_USE;    what = 0;    arg1 = 0;    arg2 = 0;    obj = null;    replyTo = null;    sendingUid = -1;    when = 0;    target = null;    callback = null;    data = null;    synchronized (sPoolSync) {        // 缓存池大小未达到上限,将自己插入到缓存池的链表头        if (sPoolSize < MAX_POOL_SIZE) {            next = sPool;            sPool = this;            sPoolSize++;        }    }}

Message.obtain(...) 最终都是调用 Message.obtain() 创建消息对象,它先尝试从共享缓存池返回一个空闲的消息对象,如果没有再去创建:

// AOSP: frameworks/base/core/java/android/os/Message.javapublic static Message obtain() {    synchronized (sPoolSync) {        // 共享缓存池不为空,弹出链表头的消息对象        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();}

Handler.post...(...)Handler.send...(...) 类函数族,如果参数列表中未带 Message 类型参数,内部实现使用 Message.obtain(...) 创建消息对象。

0 0