学习计划:2021-06-28

view.post()
使用场景
有时候使用view.getWidth()返回是0,因为这时候view还没被绘制出来。使用view.post(new Runnble)可以在view绘制完成后,在runnable里面获得view的宽高。
原理

public boolean post(Runnable action) {
    
    // ...
    
    // 判断AttachInfo是否为null
    final AttachInfo attachInfo = mAttachInfo;

    // 若不为null,直接调用其内部Handler的post ->>
    if (attachInfo != null) {
        return attachInfo.mHandler.post(action);
    }

    // 若为null,则加入当前View的等待队列
    getRunQueue().post(action); 
    return true;
}

AttachInfo在view.dispatchAttachedToWindow()方法中被赋值,所以在Activity的onCreate()方法中,AttachInfo为空,只是把runnable添加到view的队列中。

public void postDelayed(Runnable action, long delayMillis) {
    // 将传入的任务runnable封装成HandlerAction  
    final HandlerAction handlerAction = new HandlerAction(action, delayMillis);

    synchronized (this) {
        // 将要执行的HandlerAction 保存在 mActions 数组中
        if (mActions == null) {
            mActions = new HandlerAction[4];
        }

        mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
        mCount++;
    }
}

把runnable封装成HandlerAction ,并且保存在mActions 数组中,当

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中,等待执行
            handler.postDelayed(handlerAction.action, handlerAction.delay);
        }

        // 此时不再需要后续的post,将被添加到AttachInfo中
        mActions = null;
        mCount = 0;
    }

当view绘制完成后,遍历所有的任务,执行任务

View.post() 添加的任务能够保证在所有 View绘制流程结束之后才被执行,所以 执行View.post() 添加的任务时可以正确获取到 View 的宽高。

你可能感兴趣的:(学习计划:2021-06-28)