栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

View的post和postDelayed原理分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

View的post和postDelayed原理分析

文章目录
  • 前言
  • 一、post源码分析
    • 1.mAttachInfo是什么及赋值
    • 2.getRunQueue()介绍
  • 二、postDelayed源码分析
  • 总结


前言

在开发中,我们经常会使用到view的 post 方法或 postDelayed 方法,那么这两个方法有什么用呢?它们的使用原理是怎么样的呢?带着问题往下看:


一、post源码分析

代码如下:

public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
        
        getRunQueue().post(action);
        return true;
    }

从源码逻辑很清楚的看到当attachInfo 不为null时,直接调用 attachInfo.mHandler.post 执行消息,否则调用getRunQueue().post(action),最后都是交由handler去执行刷新布局。

1.mAttachInfo是什么及赋值

代码如下:

void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        mAttachInfo = info;
        if (mOverlay != null) {
            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
        }
      
        // Transfer all pending runnables.
        if (mRunQueue != null) {
            mRunQueue.executeActions(info.mHandler);
            mRunQueue = null;
        }
        // 省略无关代码
        }
 }

从上可知,mAttachInfo 是在dispatchAttachedToWindow()中赋值的,而dispatchAttachedToWindow 是在 ViewRootImpl 类的performTraversals 调用的,而这个方法在view初始化的时候会被调用,并将 ViewRootImpl 对象的 mAttachInfo 属性传递过来,赋值给 View 对象的 mAttachInfo 属性。

2.getRunQueue()介绍

代码如下:

private HandlerActionQueue getRunQueue() {
        if (mRunQueue == null) {
            mRunQueue = new HandlerActionQueue();
        }
        return mRunQueue;
    }

由上可知,getRunQueue()是返回一个HandlerActionQueue对象,并赋值给mRunQueue。
其中HandlerActionQueue的源码如下:

public class HandlerActionQueue {
    private HandlerAction[] mActions;
    private int mCount;

    public void post(Runnable action) {
        postDelayed(action, 0);
    }

    public void postDelayed(Runnable action, long delayMillis) {
        final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
        
        synchronized (this) {
            if (mActions == null) {
                mActions = new HandlerAction[4];
            }
            mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
            mCount++;
        }
    }

\省略相关代码
...
    public void executeActions(Handler handler) {
        synchronized (this) {
            final HandlerAction[] actions = mActions;
            for (int i = 0, count = mCount; i < count; i++) {
                final HandlerAction handlerAction = actions[i];
                handler.postDelayed(handlerAction.action, handlerAction.delay);
            }
            mActions = null;
            mCount = 0;
        }
    }

\省略相关代码
...
}

由上可知,当attachInfo 为null时,并执行getRunQueue().post(action)时,会将任务缓存在HandlerAction中,接下来在dispatchAttachedToWindow中会通过 mRunQueue 判断:View 添加到视图树之前,是否 View 添加了要处理的消息,如果是,则调用 mRunQueue 对象的 executeActions 方法,最终通过handler去执行任务。

二、postDelayed源码分析

原理与post一致


总结

1、post和postDelayed的原理和作用几乎一样,都是用来更新ui,差别的是postDelayed有延迟的功能。
2、mAttachInfo 对象是在 ViewRootImpl 对象初始化时创建的,并且在子 View 添加到视图树的时候,传递给子 View 的。
3、dispatchAttachedToWindow 执行的时候,会将 ViewRootImpl 对象的 mAttachInfo 属性,传递过来,并赋值给 View 对象的 mAttachInfo 属性。
4、当一个view调用 post/postDelayed 方法时,如果 mAttachInfo 不为空,表示该 View 已经添加到视图树了,直接调用 attachInfo.mHandler.post 执行消息,否则调用getRunQueue().post(action)缓存起来,当执行到dispatchAttachedToWindow时就直接调用handler的post执行任务。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/863151.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号