转载本文请联系Android开发编程公众号。前言为什么View.post()的操作可以在UI上操作,即使是在子线程中调用View.post()?今天我们来分析分析1.深入分析View.post源码1.View.post()View的post方法如下:publicbooleanpost(Runnableaction){//1。首先判断AttachInfo是否为nullfinalAttachInfoattachInfo=mAttachInfo;if(attachInfo!=null){//1.1如果不为null,则直接调用其内部Handler的postreturnattachInfo。mHandler.post(action);}//2,否则加入当前View的等待队列getRunQueue().post(action);returntrue;}AttachInfo是View的静态内部类,每个View都会持有一个AttachInfo,默认为空;如果mAttachInfo为空,则执行:将动作添加到当前视图的等待队列中;2.getRunQueue().post()看getRunQueue().post():privateHandlerActionQueuegetRunQueue(){if(mRunQueue==null){mRunQueue=newHandlerActionQueue();}returnmRunQueue;}调用HandlerActionQueue的post方法:publicvoidpost(Runnableaction){//调用postDelayed方法,有点类似Handler发送消息postDelayed(action,0);}//实际调用postDelayedpublicvoidpostDelayed(Runnableaction,longdelayMillis){//HandlerAction表示要执行的任务finalHandlerActionhandlerAction=newHandlerAction(action,delayMillisis);synchronized(this){if(mActions==null){//创建一个数组保存HandlerActionmActions=newHandlerAction[4];}//表示要执行的任务HandlerAction存储在mActions数组mActions=GrowingArrayUtils.append(mActions,mCount,handlerAction);//mActions数组索引位置累计1mCount++;}}3.HandlerActionHandlerAction表示一个待执行的任务,内部持有待执行的Runnable和延迟时间;=privatestaticclassHandlerAction{//posttaskfinalRunnableaction;//延迟时间finallongdelay;publicHandlerAction(Runnableaction,longdelay){this.action=action;this.delay=delay;}//比较是否是同一个task//用来匹配一个Runnable和对应的HandlerActionpublicbooleanmatches(RunnableotherAction){returnotherAction==null&&action==null||action!=null&&action.equals(otherAction);}}postDelayed()创建一个默认长度为4的HandlerAction数组,用于保存post()添加的任务;总结:我们调用View.post(Runnable)传入的Runnable操作在传递给HandlerActionQueue之前会被HandlerAction包装,然后缓存;当View.post(Runnable)执行时,由于此时View还没有attachToWindow,这些Runnable的操作并没有真正执行,而是先被HandlerActionQueue缓存起来;4.AttachInfo查看AttachInfo创建过程,先看它的构造方法:AttachInfo(IWindowSessionsession,IWindowwindow,Displaydisplay,ViewRootImplviewRootImpl,Handlerhandler,CallbackseffectPlayer,Contextcontext){mSession=session;mWindow=window;mWindowToken=window.asBinder();mDisplay=display;//holdthecurrentViewRootImplmViewRootImpl=viewRootImpl;//当前渲染线程HandlermHandler=handler;mRootCallbacks=effectPlayer;mTreeObserver=newViewTreeObserver(context);}AttachInfo持有当前线程的Handler;/将AttachInfo分配给当前视图。此时所有的View共享同一个AttachInfo(在同一个ViewRootImpl中)mAttachInfo=info;if(mOverlay!=null){//任何一个View都有一个ViewOverlay//ViewGroup就是ViewGroupOverlay//和直接添加ViewslikeRelativeLaout/FrameLayout,通过ViewOverlay添加的元素没有任何事件//此时主要分发给这些View浮动层!=0){mAttachInfo.mScrollContainers.add(this);mPrivateFlags|=PFLAG_SCROLL_CONTAINER_ADDED;}//mRunQueue,也就是前面的getRunQueue().post()//实际类型是HandlerActionQueue,内部保存了当前View.post的任务if(mRunQueue!=null){//使用View.post执行任务//这里注意是post到渲染线程的HandlermRunQueue.executeActions(info.mHandler);//保存延迟任务的队列设置为null,因为此时所有View共享AttachInfoRunQueue=null;}performCollectViewAttributes(mAttachInfo,visibility);//回调View的onAttachedToWindow方法//在Activity的onResume方法中调用,但是在View绘制过程之前null;if(listeners!=null&&listeners.size()>0){for(OnAttachStateChangeListenerlistener:listeners){//通知所有监听已经onAttachToWindow的View的客户端,即view.addOnAttachStateChangeListener();//但是查看尚未启动d此时绘制,所以无法正确获取测量View监听器的大小或者实际大小。onViewAttachedToWindow(this);}}}5.executeActionsmRunQueue是保存View.post()任务的HandlerActionQueue;此时调用其executeActions的方法如下:publicvoidexecuteActions(Handlerhandler){synchronized(this){//任务队列finalHandlerAction[]aactions=mActions;//遍历所有任务for(inti=0,count=mCount;i
