首先我們看下TextView
的源碼,如下圖所示:
在
TextView
的源碼中可以找到在執(zhí)行setText()
方法時一定會執(zhí)行requestLayout()
和invalidate()
方法旅掂,而在requestLayout()
中代碼如下圖所示:ViewRootImpl viewRoot = getViewRootImpl();
獲取的ViewRootImpl
類是ViewParent
接口的實現(xiàn)類而
ViewParent
接口中有requestLayout()
方法需要實現(xiàn),如下圖所示:這時后再看圖二中紅框標(biāo)注的
mParent.requestLayout()
就會發(fā)現(xiàn)mParent
其實就是一個viewParent
接口具體實現(xiàn)類的對象也就是ViewRootImpl
類再看
ViewRootImpl
中requestLayout()
的具體實現(xiàn)如下圖所示:想必到了這里大家看到
checkThread()
就已經(jīng)猜到了子線程不能更新ui的異常是怎么拋出的,還是看下具體的代碼:到了這里大家就會有疑問了,那為什么子線程
setText()
沒有異常呢酣衷,那是因為如果你圖一中的 invalidate()
方法是線程第一行代碼執(zhí)行而requestLayout()
檢查線程是個耗時操作,invalidate()
方法快于requestLayout()
檢查到線程異常就不會報錯次泽。出自古龍小李飛刀的天下武功穿仪,唯快不破!放在代碼中同樣適用意荤,想要驗證這個結(jié)論你可以在setText()
之前Thread.sleep(1000)
讓線程休眠1s試一下啊片,你就會發(fā)現(xiàn)本來正常的代碼突然拋出異常了!