View#post(Runnable)的执行流程

  • View.post(Runnable) 为什么可以得到 View 的真实宽高
  • Handler.post(Runnable)View.post(Runnable)有什么区别
  • onCreateonResume 函数中为什么无法直接得到 View 的真实宽高
  • View.post(Runnable) 中的 Runnable 是由谁来执行的,可以保证一定会被执行吗

View.post()的执行流程

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

AttachInfo 是 View 的静态内部类,每个View都会持有一个AttachInfo ,它默认为null;

View中能给mAttachInfo赋值的地方只有一处,在dispatchAttachedToWindow()方法里赋值

只初始化一次: ViewRootImpl# scheduleTraversals#performTraversals#host.dispatchAttachedToWindow(mAttachInfo, 0); 事件驱动:handler同步消息~故程序执行流程和消息执行流程~在测量结束之后执行下一个消息

#存储队列 // Assume that post will succeed later

当前AttachInfo 为空是需查看#HandlerActionQueue #本地存储队列/执行任务

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

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

 View中mAttachInfo是否为null?本地存储队列/执行任务

View中能给mAttachInfo赋值的地方只有一处,在dispatchAttachedToWindow()方法里赋值

只初始化一次: ViewRootImpl# scheduleTraversals#performTraversals#host.dispatchAttachedToWindow(mAttachInfo, 0); 事件驱动:handler同步消息~故程序执行流程和消息执行流程~在测量结束之后执行下一个消息

#存储队列 // Assume that post will succeed later

ViewRootImpl.getRunQueue().post(action);#7.0之前

getRunQueue().post(action);//7.0之后

#每个线程存在一个#7.0之前

static final ThreadLocal sRunQueues = new ThreadLocal();

#开启执行队列#故子线程和主线程执行post获取的不是同一个队列RunQueue getRunQueue().executeActions(mAttachInfo.mHandler);

不是不可以在子线程中调用View.post,要在View.onAttachToWindow之后在执行;

public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);//View.onAttachToWindow之后在可以正常使用
}// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);//View.onAttachToWindow之前不可以子线程中调用View.post
return true;
}

每个View维护一个队列#7.0之后

private HandlerActionQueue mRunQueue; getRunQueue().executeActions(mAttachInfo.mHandler);

你可能感兴趣的:(关于Android,java,jvm,redis)