转载请注明http://blog.csdn.net/chen_senhua/article/details/52202413 前几天在改项目UI的时候,发现一个bug,第一次进入APP的时候有个Bitmap不显示, 点击换图后又能显示,打个断点,才发现问题出在View.post(Runable),竟然没有执行。
之前也没看里面的实现,只是猜测里面有个Handler,现在有空就来看看里面的实现 打开View类找到方法
public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } // Assume that post will succeed later ViewRootImpl.getRunQueue().post(action); return true; }首先看mAttachInfo 何时赋值的
从代码中可以猜出,十有八九是mAttachInfo ==null 导致不执行的,既然是初始化的时候不显示,可以推断是赋值问题,找到mAttachInfo 的赋值方法
void dispatchAttachedToWindow(AttachInfo info, int visibility) { mAttachInfo = info; //... onAttachedToWindow(); //... }可以看到赋值是在 dispatchAttachedToWindow 的时候进行的,而dispatchAttachedToWindow 是在 ViewRootImpl 类的performTraversals 调用的,这方法在视图的初始化会调用,在视图发生某些改变时也会调用。(ViewRootImpl 是View 和WindowManager 的交互类). 因此可以得出结论在onAttachedToWindow之后post,必定是有效果的。
然后再看看mAttachInfo 没有被赋值的情况下怎么处理的
注释说“Assume that post will succeed later“我只是assume 他会执行,意味着-那就有一定几率不执行咯, 这个情况下他把runable放到一个队列中了,到底是放哪了呢,再看代码
static RunQueue getRunQueue() { RunQueue rq = sRunQueues.get(); if (rq != null) { return rq; } rq = new RunQueue(); sRunQueues.set(rq); return rq; }其中 sRunQueues 是ThreadLocal的实例,(ThreadLocal是一个和线程绑定的数据存储类,在不同的线程set的值得在相应相应线程才能取到,大体实现是把自身作为键值放到了Thread的Map中),他把runable放到一个ThreadLocal中去了,那么他何时去取呢?再次打开ViewRootImpl 类
performTraversals() { //.. getRunQueue().executeActions(mAttachInfo.mHandler,0) //.. } void executeActions(Handler handler) { synchronized (mActions) { final ArrayList<HandlerAction> actions = mActions; final int count = actions.size(); for (int i = 0; i < count; i++) { final HandlerAction handlerAction = actions.get(i); handler.postDelayed(handlerAction.action, handlerAction.delay); } actions.clear(); } }上面可以看出runable绕了一圈又回到了mAttachInfo.mHandler 的怀抱。
1)在View的onAttachedToWindow 之后进行post,不论在什么线程都会调用,postDelay同理。 2)在View的onAttachedToWindow 之前进行post,在主线程,可能要隔一段时间才会调用(等待 下一次 performTraversals ),在支线没有特殊处理不会被调用,postDelay同理,并且delay的时间偏差可能较大。 3)在一个View没有添加到窗口中时,也就不会调用onAttachedToWindow ,所以效果同第二条。