自定義View-RootView和DecorView

ViewRoot指的是ViewRootImpi,它是連接WindowManager和DecorView的橋梁速蕊,view的三大流程(測量娘赴、布局、繪制)都需要ViewRoot來完成诽表。

  • 它是view的根隅肥,他控制View的測量袄简、布局绿语、繪制
  • 它持有WindowSession通過Binder與WMS通信。

目錄

  • ViewRoot在哪里被創(chuàng)建又如何關(guān)聯(lián)DecorView和WindowManager的
  • ViewRoot是如何完成view的三大流程
  • DecorView的基礎(chǔ)概念

1. ViewRoot在哪里被創(chuàng)建又如何關(guān)聯(lián)DecorView和WindowManager的

ViewRootImpl是在WindowManagerGlobal的addView()發(fā)方法中被創(chuàng)建的吕粹。當Activity在ActivityThread中被創(chuàng)建后緊接著會將DecorView添加到Window中,同時也會創(chuàng)建ViewRootImpl匹耕,并將ViewRootImpi和DecorView關(guān)聯(lián)起來。
下面為WindowManagerGlobal中addView()的部分源碼:

public void addView(View view, ViewGroup.LayoutParams params,
                    Display display, Window parentWindow){
    ...
    synchronized (mLock) {
        ...
        //創(chuàng)建ViewRootImp
        root = new ViewRootImpl(view.getContext(), display);
        ...
    }
    try {
         //關(guān)聯(lián)WindowManager和DocorView
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
        ...
        throw e;
    }
}

下面為ViewRoot的setView()的部分源碼

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
         ...
        mView = view;
            ...
        requestLayout();
            ...
        try {
                ...
            res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                    getHostVisibility(), mDisplay.getDisplayId(),
                    mAttachInfo.mContentInsets, mInputChannel);
        } catch (RemoteException e) {
               ...
        }
    }
}

在setView中傳入的view就是DecorView他被賦值給mView這個會在performTraversals()中賦值給host用于參與頂層view的測量和繪制驶赏。setView()方法還會先調(diào)用requestLayout()煤傍,完成布局的第一次layout過程损趋,然后調(diào)用addToDisplay(),來添加Window(mWindowSession.addToDisplay調(diào)用的是Session的addToDisplay()方法)。

  @Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
                        int viewVisibility, int displayId, Rect outContentInsets,
                        InputChannel outInputChannel) {
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
            outContentInsets, outInputChannel);
}

2. ViewRoot是如何完成view的三大流程

performTraversals()方法調(diào)用是通過scheduleTraversals()中handler去異步調(diào)用mTraversalRunnable接口該蒋失,最后該接口中的run()方法又調(diào)用了doTraversal()方法才調(diào)起了performTraverse()桐玻。

void doTraversal() {
    if (mTraversalScheduled) {
       ...
        try {
            performTraversals();
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
        ...
    }
}

ViewRoot的performTraversals()是該類的核心,因為真正開始繪制是從調(diào)用這個方法開始铣卡。

performTraversals()部分源碼:

private void performTraversals() {
    //將DecorView賦值給host偏竟,用于view的測量、布局和繪制
    final View host = mView;
    if (!mStopped) {
          ...
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
          ...
    }
          ...
    if (didLayout) {
        performLayout(lp, desiredWindowWidth, desiredWindowHeight);
         ...
    }
    if (!cancelDraw && !newSurface) {
         ...
        performDraw();
    }
    ...
}

3. DecorView的基礎(chǔ)概念

DecorView是界面的頂級View,一般它是由一個豎向的LinearLayout和狀態(tài)欄組合成(一些特殊機型還會有導航欄)蝉仇,LinearLayout布局中有標題欄和內(nèi)容欄(content)組合而成(可參考下圖)。

  • 內(nèi)容欄是一個FrameLayout布局
  • Activity的setConentView()方法就是在內(nèi)容欄中增加View
  • findViewById(android.R.id.content)獲取的是內(nèi)容欄
  • contentView.getChildAt(0)獲取的是當前Activity布局文件的跟布局沉迹,也就是我們在layout文件設(shè)置的頂層的view害驹。

下圖為DecorView的層級關(guān)系圖:


image

參考

Android窗口機制(四)ViewRootImpl與View和WindowManager

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宛官,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子进宝,更是在濱河造成了極大的恐慌枷恕,老刑警劉巖谭胚,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灾而,死亡現(xiàn)場離奇詭異,居然都是意外死亡昼激,警方通過查閱死者的電腦和手機锡搜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凡傅,“玉大人肠缔,你說我怎么就攤上這事∶魑矗” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵猫态,是天一觀的道長。 經(jīng)常有香客問我偏螺,道長匆光,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任夺巩,我火速辦了婚禮周崭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘美澳。我一直安慰自己摸航,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布雨膨。 她就那樣靜靜地躺著读串,像睡著了一般。 火紅的嫁衣襯著肌膚如雪排监。 梳的紋絲不亂的頭發(fā)上胀茵,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音峭弟,去河邊找鬼脱拼。 笑死,一個胖子當著我的面吹牛情臭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俯在,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼跷乐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了馒稍?” 一聲冷哼從身側(cè)響起浅侨,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鼓黔,沒想到半個月后不见,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年盖高,在試婚紗的時候發(fā)現(xiàn)自己被綠了喻奥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捏悬。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖甥厦,靈堂內(nèi)的尸體忽然破棺而出寇钉,到底是詐尸還是另有隱情,我是刑警寧澤扫倡,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站锥累,受9級特大地震影響集歇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鬼悠,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一焕窝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧它掂,春花似錦虐秋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至桩引,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間血崭,已是汗流浹背厘灼。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工手幢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人围来。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像桶错,于是被迫代替她去往敵國和親航唆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容