1. 程式人生 > >Android檢視架構詳解

Android檢視架構詳解

轉載請註明原作者、文章來源,連結,版權歸原文作者所有。

 最近一直在研究View的繪製相關的機制,發現需要補充一下Android View Architecture的相關知識,所以就特地研究了一下這方面的程式碼,寫成本篇文章
 為了節約你的時間,本篇文章內容大致如下:

  • ActivityDecorViewPhoneWindowViewRoot的作用和相關關係

Android View Architecture

 先來幾張圖,大致展現一下Android 檢視架構的大概。

感謝網友提醒,泛化和實現這兩種關係的箭頭畫反啦。以後要仔細學一遍UML了,平時經常畫,如果有錯誤可真是鬧笑話啊。

Android View Architecture

View各類關係圖

View樹狀圖

Activity和Window

 總所周知,Activity並不負責檢視控制,它只是控制生命週期和處理事件,真正控制檢視的是Window。一個Activity包含了一個Window,Window才是真正代表一個視窗,也就是說Activity可以沒有Window,那就相當於是Service了。在ActivityThread中也有控制Service的相關函式或許正好印證了這一點。
ActivityWindow的第一次邂逅是在ActivityThread呼叫Activityattach()函式時。

//[window]:通過PolicyManager建立window,實現callback函式,所以,當window接收到
//外界狀態改變時,會呼叫activity的方法, final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor) { .... mWindow = PolicyManager.makeNewWindow(this
); //當window接收系統傳送給它的IO輸入事件時,例如鍵盤和觸控式螢幕事件,就可以轉發給相應的Activity mWindow.setCallback(this); ..... //設定本地視窗管理器 mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); ..... }

 在attach()中,新建一個Window例項作為自己的成員變數,它的型別為PhoneWindow,這是抽象類Window的一個子類。然後設定mWindowWindowManager

Window,Activity和DecorView

DecorViewFrameLayout的子類,它可以被認為是Android檢視樹的根節點檢視。DecorView作為頂級View,一般情況下它內部包含一個豎直方向的LinearLayout,在這個LinearLayout裡面有上下兩個部分(具體情況和Android版本及主體有關),上面的是標題欄,下面的是內容欄。在Activity中通過setContentView所設定的佈局檔案其實就是被加到內容欄之中的,而內容欄的id是content,在程式碼中可以通過ViewGroup content = (ViewGroup)findViewById(R.android.id.content)來得到content對應的layout。
Window中有幾個檢視相關的比較重要的成員變數如下所示:

  • mDecor:DecorView的例項,標示Window內部的頂級檢視
  • mContentParent:setContetView所設定的佈局檔案就加到這個檢視中
  • mContentRoot:是DecorView的唯一子檢視,內部包含mContentParent,標題欄和狀態列。

 Activity中不僅持有一個Window例項,還有一個型別為ViewmDecor例項。這個例項和Window中的mDecor例項有什麼關係呢?它又是什麼時候被建立的呢?
 二者其實指向同一個物件,這個物件是在Activity呼叫setContentView時建立的。我們都知道ActivitysetContentView實際上是呼叫了WindowsetContentView方法。

@Override
public void setContentView(int layoutResID) {
    if (mContentParent == null) { //[window]如何沒有DecorView,那麼就新建一個
        installDecor(); //[window]
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    ....
    //[window]第二步,將layout新增到mContentParent
    mLayoutInflater.inflate(layoutResID, mContentParent);
    .....
}

 程式碼很清楚的顯示了佈局檔案的檢視是新增到mContentParent中,而且Window通過installDecor來新建DecorView

//[window]建立一個decorView
private void installDecor() {
    if (mDecor == null) {
        mDecor = generateDecor(); //直接new出一個DecorView返回
        ....
    }
    if (mContentParent == null) {
        //[window] 這一步也是很重要的.
        mContentParent = generateLayout(mDecor); //mContentParent是setContentVIew的關鍵啊
        .....
    }
    ....
}
protected ViewGroup generateLayout(DecorView decor) {
    // Apply data from current theme.
    .......
    //[window] 根據不同的style生成不同的decorview啊
    View in = mLayoutInflater.inflate(layoutResource, null);
    // 加入到deco中,所以應該是其第一個child
    decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mContentRoot = (ViewGroup) in; //給DecorView的第一個child是mContentView
    // 這是獲得所謂的content 
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    }
    .....
    return contentParent;
}

 從上述的程式碼中,我們可以清楚的看到mDecormContentParentmContentRoot的關係。
 那麼,Activity中的mDecor是何時被賦值的?我們如何確定它和Widnow中的mDecor指向同一個物件呢?我們可以檢視ActivityThreadhandleResumeActivity函式,它負責處理Activityresume階段。在這個函式中,Android直接將Window中的DecorView例項賦值給Activity

final Activity a = r.activity;
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;

Window,DecorView 和 ViewRoot

ViewRoot對應ViewRootImpl類,它是連線WindowManagerServiceDecorView的紐帶,View的三大流程(測量(measure),佈局(layout),繪製(draw))均通過ViewRoot來完成。ViewRoot並不屬於View樹的一份子。從原始碼實現上來看,它既非View的子類,也非View的父類,但是,它實現了ViewParent介面,這讓它可以作為View的名義上的父檢視。RootView繼承了Handler類,可以接收事件並分發,Android的所有觸屏事件、按鍵事件、介面重新整理等事件都是通過ViewRoot進行分發的。ViewRoot可以被理解為“View樹的管理者”——它有一個mView成員變數,它指向的物件和上文中WindowActivitymDecor指向的物件是同一個物件

 我們來先看一下ViewRoot的建立過程。由於ViewRoot作為WindowMangerServiceDecorView的紐帶,只有在WindowManager將持有DecorViewWindow新增進視窗管理器才建立。我們可以檢視WindowMangerGlobal中的addView函式。對WindowManager不太熟悉的同學可以參考《Window和WindowManager解析》

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
        // 建立ViewRootImpl,然後將下述物件新增到列表中
    ....
    root = new ViewRootImpl(view.getContext(), display);

    view.setLayoutParams(wparams);

    mViews.add(view);
    mRoots.add(root);
    mParams.add(wparams);
    ....
    try {
        // 新增啦!!!!!!!!這是通過ViewRootImpl的setView來完成,這個View就是DecorView例項
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
      ....
    }
    ....
}

 那麼,Window是什麼時候被新增到WindowManager中的呢?我們回到ActivityThreadhandleResumeActivity函式。我們都知道Activity的resume階段就是要顯示到螢幕上的階段,在Activity也就是DecorView將要顯示到螢幕時,系統才會呼叫addView方法。
 我們在handleResumeActivity函式中找到了下面一段程式碼,它呼叫了ActivitymakeVisible()函式。

// ActivityThread
r.activity.makeVisible();

//Activity
    //[windows] DecorView正式新增並顯示
    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

 我們通過原始碼發現,正式在makeVisible函式中,系統進行了Window的新增。

相關推薦

Android檢視架構

轉載請註明原作者、文章來源,連結,版權歸原文作者所有。  最近一直在研究View的繪製相關的機制,發現需要補充一下Android View Architecture的相關知識,所以就特地研究了一下這方面的程式碼,寫成本篇文章  為了節約你的時間,

Android系統架構(3)-Android Libraries

3.Android Libraries 作者:李利偉不V 今天講解Libraries層 Android的Libraries層對應一般嵌入式系統,相當於中介軟體層次。Android 的各種庫一般是以系統中介軟體的形式提供的,它們均有的一個顯著特點就是與移動裝置的平臺

android系統架構

先放上一張android系統架構圖: 從上圖中可以看出,Android系統架構為四層結構,從上層到下層分別是:應用程式層、應用程式框架層、系統執行庫層以及Linux核心層,分別介紹如下: 1)應用程式層 Android平臺的應用層上包括各類與使用者直接互動的應用程式,

Facebook移動架構Android Flux架構

要為Android應用找到一個好的架構不是一件容易的事情。谷歌似乎不太在乎這個事情,因此在設計模式上,除了Activity 生命週期管理之外,再也沒有官方的推薦。 但是,為你的應用打造一個架構是非常重要的。不管你是否喜歡,任何應用最終都會有一個架構。因此你

Android直播開發之旅(7):Android視訊直播核心技術(架構)

(轉載請宣告出處:http://blog.csdn.net/andrexpert/article/details/76919535) 一、直播架構解析      目前主流的直播架構中主要有兩種方案,即流媒體轉發、P2P。流媒體轉發,是一種在視訊直播中以流的方式將連續的音、

高並發高流量網站架構

高並發高流量網站架構詳解(推薦)高並發高流量網站架構詳解Web2.0的興起,掀起了互聯網新一輪的網絡創業大潮。以用戶為導 向的新網站建設概念,細分了網站功能和用戶群,不僅成功的造就了一大批新生的網站,也極大的方便了上網的人們。但Web2.0以用戶為導向的理念,使得新 生的網站有了新的特點——高並發,高流量,數

OSI七層與TCP/IP五層網絡架構

p地址 tro 簡單 流控 之間 模型 網卡 層次結構 user OSI和TCP/IP是很基礎但又非常重要的網絡基礎知識,理解得透徹對運維工程師來說非常有幫助。今天偶又復習了一下:   (1)OSI七層模型   OSI中的層 功能 TCP/IP協議族   應用層 文件傳輸,

aNDROID之MEDIapLaYER

iap music media 詳解 list oid aid 5% layer %E8%BD%AC%E8%BD%BD%E4%B8%80%E4%B8%AA%E5%9B%BE%E7%89%87%E5%A4%84%E7%90%86%E5%B7%A5%E5%85%B7%E7%B1

Flume日誌收集系統架構--轉

with 指定 mwl 裏程碑 工程 生命 數據接收 dba -i 2017-09-06 朱潔 大數據和雲計算技術 任何一個生產系統在運行過程中都會產生大量的日誌,日誌往往隱藏了很多有價值的信息。在沒有分析方法之前,這些日誌存儲一段時間後就會被清理。隨著技術的發展和

zabbix實現原理及架構

收集 信息 核心 狀態 start 原理 整體架構 比較 zabbix 想要用好zabbix進行監控,那麽我們首要需要了解下zabbix這個軟件的實現原理及它的架構。建議多閱讀官方文檔。 一、總體上zabbix的整體架構如下圖所示: 重要組件說明: 1)zabbix se

【轉載】FusionSphere架構

computing ssis 修改 hyperv 適配器 drive 特殊 架構 avi FusionSphere底層使用Xen架構: 1.單臺物理機上建立hypervisor系統。 2.將所有單個hypervisor系統整合起來管理使用。 安裝C

Android RxJava操作符系列: 變換操作符

urn 原因 轉換 需要 生產 依賴 reat 入門 所有 Rxjava,由於其基於事件流的鏈式調用、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。Github截圖 如果還不了解 RxJava,請看文章:Android:這是一篇 清晰 &

NopCommerce源碼架構

body clear get main 都是 反轉 ace 通過 .com NopCommerce源碼架構詳解--初識高性能的開源商城系統cms 很多人都說通過閱讀、學習大神們高質量的代碼是提高自己技術能力最快的方式之一。我覺得通過閱讀NopCommerce

android:exported 屬性

itl fas 默認 之前 綁定 四大 nbsp ring ins http://blog.csdn.net/watermusicyes/article/details/46460347 昨天在用360掃描應用漏洞時,掃描結果,出來一個android:exported屬性,

openstack架構

服務組 rest opensta volume config -s ins serve 三臺 需要的軟件:RHEL7OSP-8.0-20160421-x86_64.isoopenstack 雲:形象化的說法分類:Iaas:基礎架構即服務 提供雲主機Paas:平臺即服務

RESTful 架構

但是 就是 per 設置 產生 mce 計數器 計時 混淆 原文章地址:http://www.runoob.com/w3cnote/restful-architecture.html 1. 什麽是REST REST全稱是Representational State T

dkhadoop大數據處理架構

hadoop大數據處理架構 大數據處理架構hadoop 大數據處理架構 大數據的時代已經來了,信息的爆炸式增長使得越來越多的行業面臨這大量數據需要存儲和分析的挑戰。Hadoop作為一個開源的分布式並行處理平臺,以其高拓展、高效率、高可靠等優點越來越受到歡迎。這同時也帶動了hadoop商業版的發行。

Android SDK Manager

eba 調試 測試工具 使用說明 服務 能力 bar 部分 以及 Android基礎知識——Android SDK Manager詳解 做Android開發時,免不了使用Android SDK Manager,安裝需要的sdk版本、buildTool

守護客戶數據價值:企業級NewSQL HTAP分布式雲TBase架構

最大 就是 global 友好 proc master 分表 網絡 enc 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 作者:jasonys,隸屬於騰訊技術工程事業群數據平臺部,負責TBase數據的技術研發和架構設計,有超過10年的數據庫內核開發設計經驗,

區塊鏈錢包開發系統架構

有一個 系統 丟了 功能 設置 key 銀行卡 代幣 keystore 隨著國內區塊鏈數字貨幣交易平臺的逐步完善,區塊鏈錢包開發和使用會越來越頻繁和重要,在使用區塊鏈錢包時,有幾個名詞必須深刻理解:1、什麽是區塊鏈錢包地址可以把區塊鏈錢包地址想象成一個銀行卡號,別人可以給你