0,參考:
Android_8.0.0 源碼
分析 view.post() 爲什麼能夠 獲取 View的寬高
1,核心內容
/**
* main 在主線程調用
*/
public static void main() {
LogUtil.v("1");
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
LogUtil.v("2");
}
});
LogUtil.v("3");
try {
Thread.sleep(1000); // 模擬一個超級耗時的操作
} catch (InterruptedException e) {
e.printStackTrace();
}
LogUtil.v("4");
}
問題:在主線程 調用 「main方法」,打印順序是怎麼樣的,會不會受到延時的影響
結論:1 -> 3 -> 4 -> 2
原因:一個方法爲一個執行單元。系統調用到「main方法」時,post 將 runnable 插入到Looper隊列中。因此,runnable 必須等待「main方法」執行完成,纔會被執行
2,獲取寬高的原因【1基礎上的實戰】
ViewRootImpl.java中,performTraversals方法,該方法也是分發measure、layout、draw的實際入口
private void performTraversals() {
// 實際可能 post Runnable 的兩個地方
host.dispatchAttachedToWindow(mAttachInfo, 0); // line:1658
getRunQueue().executeActions(mAttachInfo.mHandler); // line:1697
// 實際分發實現
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); // line:2155
performLayout(lp, mWidth, mHeight); // line:2200
performDraw(); // line:2347
}
調用順序如代碼中所示,執行 “放入runnable” 的代碼,是在 performMeasure、performLayout、performDraw 這三個方法之前的。而我們能在 Runnable 中,獲取到測量完成之後的寬高,就是因爲 Runnable 被 插入到 Looper 隊列中。因此,runnable 被執行的代碼,是在 performTraversals 方法結束之後,才被調用的。
因此,runnable 中的代碼,就能夠獲取到 performTraversal 執行完成之後的數值。即:寬、高等數據