Handler 實際應用 - 獲取View的寬高

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 執行完成之後的數值。即:寬、高等數據

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章