View的post()源码分析

##View的post()和postDelayed()方法详解

###子线程中不能对UI进行操作,这我们都知道,但是可以通过view.post(Runnable)的方式进行UI操作,这是为什么呢?我们通过分析源码的方式来了解一下

    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;

    }

view的post()将Runnable action传递给attachInfo.Handler,所以其本质都是Handler、Looper、MessageQueue、Message的异步消息处理机制,接着再查看mAttachInfo的来源,源码定位到

     void dispatchAttachedToWindow(AttachInfo info, int visibility) {

        mAttachInfo = info;

        …

    }

####在view的绘制过程中,第一次会调用DecorView的dispatchAttachedToWindow,所以这也就解释了view.post()可以解决在oncreate()中获取view的宽高为0的问题

` getRunQueue().post(action); `当attachInfo为空时会走此方法,getRunQueue()的源码:

    private HandlerActionQueue getRunQueue() {

        if (mRunQueue == null) {

            mRunQueue = new HandlerActionQueue();

        }

        return mRunQueue;

    }

再看HandlerActionQueue的源码:

    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会将runnable缓存起来,最大缓存数为4,缓存起来的Runnable返回到上面的dispatchAttachedToWindow中会被调用

    原文作者:zc2echo
    原文地址: https://blog.csdn.net/android_ErChen/article/details/79391609
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞