Android消息机制,从Java层到Native层剖析

这篇博文详细探讨了Android消息机制,从Java层的Handler、MessageQueue、Looper到Native层的实现。Java层中,消息产生源于Message对象,通过BlockingRunnable进行处理,利用ThreadLocal维持线程内对象的唯一性。Native层则涉及MessageEnvelope和fd的处理。整个机制包括消息产生、投递、处理和分发,揭示了Android线程间通信的底层原理。
摘要由CSDN通过智能技术生成

由Handler、MessageQueue、Looper构成的线程消息通信机制在Android开发中非常常用,不过大部分人都只粗浅地看了Java层的实现,对其中的细节不甚了了,这篇博文将研究Android消息机制从Java层到Native层的实现。

消息机制由于更贴近抽象设计,所以整个结构更简单,只包含了消息的产生、分发,不像Input子系统那样还有归类、过滤等环节。整体的结构如下图:

Android Java层消息机制

消息的产生

在Java层中消息的产生都来源于用户创建的Message对象,经过封装的Runnable对象,或调用obtainMessage从Message Pool中获得,Message Pool指的是Message类内的Message循环队列,队头是静态的Message对象sPool,该队列最大容纳MAX_POOL_SIZE(50)个Message:

MessagePool对Message的复用节省了不断创建Message带来的开销,如果当前50个Message都已经被用过,由于MessagePool是循环队列,则会回到队头并请空该Message,向下复用。

BlockingRunnable

看Java层Handler的源码的时候发现了一个奇怪的东西:BlockingRunnable,基本上没有用过的东西,也没看别人讲过,于是我就来钻研一下吧:

private static final class BlockingRunnable implements Runnable {
   
    private final Runnable mTask;
    private boolean mDone;

    public BlockingRunnable(Runnable task) {
        mTask = task;
    }

    @Override
    public void run() {
        try {
            mTask.run();
        } finally {
            synchronized (this) {
                mDone = true;
                notifyAll();
            }
        }
    }

    public boolean postAndWait(Handler handler, long timeout) {
        if (!handler.post(this)) {
            return false;
        }

        synchronized (this) {
            if (timeout > 0) {
                final long expirationTime = SystemClock.uptimeMillis() + timeout;
                while (!mDone) {
                    long delay = expirationTime - SystemClock.uptimeMillis();
                    if (delay <= 0) {
                        return false; // timeout
                    }
                    try {
                        wait(delay);
                    } catch (InterruptedException ex) {
                    }
                }
            } else {
                while (!mDone) {
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }
        return true;
    }
}

我们可以看到,BlockingRunnable是一个“包裹”构造方法中传入的Runnable的Runnable,调用BlockingRunnable的postAndWait会做以下事情:

  1. 如果投递BlockingRunnable失败,返回false
  2. 锁住投递BlockingRunnable的线程
  3. 如果timeout大于0,计算参数Runnable的到期时间,只要参数Runnable还没处理完,则一直轮询还剩多少时间,并调用wait(delay)让投递BlockingRunnable的线程继续等待,直参数Runnable处理完(mDone为true)这个过程才结束
  4. 如果timeout小于等于0,而且参数Runnable还没处理完,则一直等待直到参数Runnable处理完(mDone为true)

这个东西的说明书和使用风险可以在runWithScissors方法的注释里看到,我在这里就不当翻译工了。

消息的投递和处理

得到Message后,就会通过Handler的sendMessageAtTime调用MessageQueue的enqueueMessage将Message投递到MessageQueue中,在往下学习之前必须先了解Handler的创建,因为后面的知识和它有关联。

Handler的创建和初始化

其实Handler的初始化没什么好看的,就是保存Callback、mLooper的MessageQueue的引用,以及声明Handler是否异步投递所有Message。但是里面有一个内存泄露的检查,可以学习一下,就是如果打开了FIND_POTENTIAL_LEAKS,就会进行内存泄露的检查,它会做以下事情:

  1. 获取当前Handler类
  2. 如果Handler是匿名内部类,或成员类,或局部类,且Handler的修饰符不是stat
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值