Android view post(runnable)分析

本文详细分析了Android中view.post(Runnable)的实现原理,包括源码解析、mAttachInfo初始化、RunQueue的工作流程以及与Activity生命周期的关系。在Activity的onCreate中直接获取view大小为0,但通过view.post(Runnable)可以在view被正确测量后获取尺寸。view.post()的本质是将Runnable添加到消息队列,并在UI线程中执行,与Handler.post()类似。在API 24以下版本,线程间RunQueue不同可能导致Runnable未执行。通过对dispatchAttachedToWindow的跟踪,发现它在Activity的onResume之后被调用,因此在onResume时无法获取view尺寸。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先来看下这些疑问:

  1. handler post和view post有什么区别?
  2. 在Activity生命周期onCreate中直接获取view的大小为0,这时通常使用view.post(runnable)方式来获取就能成功。为什么通过这种方式就可以哪?
  3. 在App启动速度一文中提到,为了不影响Activity启动速度,可以把一些耗时的操作通过view.post(runnable)放在第一帧绘制完成后进行。怎么确定这样就是在第一帧绘制完成后执行的哪?

handler post会把Runnable封装成Message,然后走消息机制那些流程。如果在获取view大小时通过handler post可以吗?来看下view post的实现。

源码分析

view post(runnable)

    /**
     * <p>Causes the Runnable to be added to the message queue.
     * The runnable will be run on the user interface thread.</p>
     */
    public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }

        // Postpone the runnable until we know on which thread it needs to run.
        // Assume that the runnable will be successfully placed after attach.
        getRunQueue().post(action);
        return true;
    }

注释可以看到这里的Runnable和Hanlder post中的一样被加入到消息队列中,并且将会在UI线程中执行。具体到代码时跟view的mAttachInfo有关:

  • 不为空时,runnable会通过mHandler对象发送到UI线程的MessageQueue中,这样的话就跟普通handler post没什么区别了。(为什么是ui线程可以通过mHandler的注释得到验证)
  • 为空时,将runnable放入RunQueue中。
    那么post到RunQueue里的runnable什么时候执行呢,又是为何当View还没attach到window的时候,需要post到RunQueue中。

mAttachInfo 什么时候初始化的哪?RunQueue又是什么哪?

mAttachInfo的初始化

此对象的初始化在 View的dispatchAttachedToWindow()里

void dispatchAttachedToWindow(AttachInfo info, int visibility) {
    mAttachInfo = info;
   ...
    //  在此会执行处理RunQueue里的runnable,稍后再介绍
    if (mRunQueue != null) {
        mRunQueue.executeActions(info.mHandler);
        mRunQueue = null;
    }
  ...
    onAttachedToWindow();
}

可以看到只有当view attch到Window后,才会给mAttachInfo赋值,并且接下来会直接执行 getRunQueue().post(action) 。接下来我们看下RunQueue到底是什么以及executeActions()的实现。

RunQueue

private HandlerActionQueue getRunQueue() {
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值