015.ViewRoot和DecorView
學習工作原理的話,首先要知道View有三大流程,測量流程、佈局流程、繪製流程。之後再學習一些常見的回調方法,這樣在我們寫自定義View的時候,就能更加得心應手了。
1.ViewRoot:
ViewRoot對應ViewRootImpl類,它連接着WindowManager和DecorView。View的三大流程,都是同個ViewRoot來實現的。在ActivityThread中,當Activity對象被創建以後,會把Decorview添加到Window中,並且會創建ViewRootImpl對象,同時將ViewRootImpl和DecorView關聯起來。
ActivityThread中handleResumeActivity方法可以看到:
//表示剛創建的Activity
if (r.window == null && !a.mFinished && willBeVisible) {
//創建窗口,賦予Activity
r.window = r.activity.getWindow();
//獲取DecorView
View decor = r.window.getDecorView();
//設置不可見
decor.setVisibility(View.INVISIBLE);
//獲取WindowManager
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
//添加
wm.addView(decor, l);
}
}
wm.addView( decor, l ) 是調用WindowManagerGlobal的addView方法,在WindowManagerGlobal的addView方法中,有如下代碼:
……………………
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
View的繪製流程師從ViewRoot的performTraversals開始的。如上面,就是依次執行ViewRoot的setView->requestLayout->scheduleTraversals->scheduleTraversalRunnable#run->performTraversals方法。
繪製出一個View,需要經過measure,layout和draw。
在performTraversals中,會依次調用performMeasure、performLayout和performDraw三個方法,分別完成頂級View的measure、layout和draw三大流程。其中measure、layout和draw都和之前事件分發機制一樣,performMeasure->measure->onMeasure->子View
measure->onMeasure ……流程就像事件傳遞一樣傳遞下去。如此反覆,就遍歷了整個View樹。
measure過程決定了View的寬高,Measure完成了以後,可以通過getMeasureWidth和getMeasureHeight方法來獲取到View測量後的寬高,一般情況下,這時候得到的寬高就是View最終的寬高,但是,有特殊情況。Layout過程決定了最終View的四個訂單的座標和實際的寬高。可以通過getTop getBottom getLeft
getRight 拿到View的四個頂點的位置,並且可以通過getWidth和getHeight拿到View最終的寬高。Draw的過程決定了View的顯示,只有draw方法完成以後view的內容才能顯示在屏幕上。
2.DecorView
DecorView是我們Activity的頂級View,一般情況,DecorView包含着一個vertical的LinearLayout,上面是一個titlebar 下面是一個ViewGroup id就是android.R.id.content,所以我們Activity是setContentView
同時,DecorView其實是一個FrameLayout,View層的事件都先經過DecorView,然後才傳遞給我們的View.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.