android View.post()分析

本文深入解析了Android中View类的post()和postDelayed()方法的工作原理,阐述了这两种方法如何确保在UI线程中执行任务,以及它们在不同场景下的应用,特别是与Handler机制的交互。

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

大家都知道每个View都有一个post()和postDelayed()方法,那么这两个方法是做什么用呢?什么时候需要用呢?

我们带着这两个问题来分析一下:

首先我们看下这两个方法的源码,首先看post():

/**
 * <p>Causes the Runnable to be added to the message queue.
 * The runnable will be run on the user interface thread.</p>
 *
 * @param action The Runnable that will be executed.
 *
 * @return Returns true if the Runnable was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 *
 * @see #postDelayed
 * @see #removeCallbacks
 */
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;

}

从源码中我们很清楚的看到,两种情况:

1.当mAttachInfo != null 时,post方法最终是由attachInfo中的mHandler调用post来处理,从而保证在ui线程中执行,所以从根本上来之后的整个流程还是Handler 的整个处理机制流程(Handler的处理机制流程,这里不做分析),那么mAttachInfo又是什么时候赋值的呢?搜索一下源码看到:

/**
 * @param info the {@link android.view.View.AttachInfo} to associated with
 *        this view
 */
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
    mAttachInfo = info;
    if (mOverlay != null) {
        mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);

    }

 

可以看到mAttachInfo是在dispatchAttachedToWindow中调用的,而dispatchAttachedToWindow 是在 ViewRootImpl 类的performTraversals 调用的,而这个方法在view初始化的时候会被调用。

2.mAttachInfo==null时,调用getRunQueue().post(action),我们来看下这个getRunQueue()的源码:

/**
 * Returns the queue of runnable for this view.
 *
 * @return the queue of runnables for this view
 */
private HandlerActionQueue getRunQueue() {
    if (mRunQueue == null) {
        mRunQueue = new HandlerActionQueue();
    }
    return mRunQueue;

}

 

这里看到最终调用的是HandlerActionQueue的post()方法:

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++;
    }

}

这里我们看到基本上就是通过HandlerActionQueue缓存起来,缓存起来什么时候执行呢?我们找下HandlerActionQueue的源码里:

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;
    }

}

缓存起来的runnable最终还是通过handler来执行,直接找到执行的代码:

 

还是通过dispatchAttachedToWindow来执行。

这两个方法:

当打开一个activity时如果调用post方法时还没有开始执行dispatchAttachedToWindow就先调用getRunQueue().post(action)缓存起来,当执行到dispatchAttachedToWindow时再执行handler的post,如果到达就直接执行handler.post。

总结:post()和postDelayed()用来更新ui,postDelayed可以设置延时。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值