android activity與view的聯繫--window

第8章 理解Window和WindowManager / 294
8.1 Window和WindowManager / 294
8.2 Window的內部機制 / 297
8.2.1 Window的添加過程 / 298
8.2.2 Window的刪除過程 / 301
8.2.3 Window的更新過程 / 303
8.3 Window的創建過程 / 304
8.3.1 Activity的Window創建過程 / 304
8.3.2 Dialog的Window創建過程 / 308

8.3.3 Toast的Window創建過程 / 311


Activity是Android應用程序的載體,允許用戶在其上創建一個用戶界面,並提供用戶處理事件的API,如 onKeyEvent, onTouchEvent等。 並維護應用程序的生命週期。Activity本身是個龐大的載體,可以理解成是應用程序的載體,如果木有Activity,android應用將無法運 行。也可以理解成 android應用程序的入口。Acivity的實例對象由系統維護。系統服務ActivityManager負責維護Activity的實例對象,並根 據運行狀態維護其狀態信息。

當我們調用Acitivity的 setContentView方法的時候實際上是調用的Window對象的setContentView方法,所以我們可以看出Activity中關於界 面的繪製實際上全是交給Window對象來做的。繪製類圖的話,可以看出Activity聚合了一個Window對象。

 在該方法中,首先創建一個DecorView,DecorView是一個擴張FrameLayout的類,是所有窗口的根View。我們在Activity中調用的setConctentView就是放到DecorView中了。這是我們類圖的聚合關係如下:

Activity--->Window--->DecorView

 Activity創建後系統會調用其attach方法,將其添加到ActivityThread當中,在attach方法中創建了一個window對象。window對象是一個抽象類。要注意window對象創建時並木有創建 Decor對象。用戶在Activity中調用setContentView,然後調用window的setContentView,這時會檢查 DecorView是否存在,如果不存在則創建DecorView對象,然後把用戶自己的View 添加到DecorView中。

 在ActivityThread當中調用wm.addView(decor, l);把它加入到window manager proxy的mViews中,同時爲這個decor view創建一個ViewRoot,ViewRoot負責協調decorview與windowmanager直接繪圖、事件處理。說簡單點就是 DecorView是客戶端所有view的根,window manager proxy爲這個decorview創建一個ViewRoot和Window manager service打交道

 我們可以去看看DecorView的實現,它是PhoneWindow的一個內部類。實 現很簡單,它默認會包含一個灰色的標題欄,然後在標題欄下邊會包含一個空白區域用來當用戶調用setContentView的時候放置用戶View,並傳 遞事件。

Android DecorView淺析

一、DecorView爲整個Window界面的最頂層View。

二、DecorView只有一個子元素爲LinearLayout。代表整個Window界面,包含通知欄,標題欄,內容顯示欄三塊區域。

三、LinearLayout裏有兩個FrameLayout子元素。

  (20)爲標題欄顯示界面。只有一個TextView顯示應用的名稱。也可以自定義標題欄,載入後的自定義標題欄View將加入FrameLayout中。

  (21)爲內容欄顯示界面。就是setContentView()方法載入的佈局界面,加入其中。

工具查看:

1.

下圖爲SDK中tools文件夾下hierarchyviewer bat 查看ViewTree的結果:

(此時未替換標題欄)

 

2.替換標題欄後ViewTree的變化:

綠色區域發生了變化,改變爲了載入的title.xml文件的佈局。

title.xml內容爲:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <ImageView
    android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/icon2"/>
  <TextView
      android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:id="@+id/title_tv"
  android:textColor="#FFFFFF"
  android:textStyle="bold"
  android:text="@string/app_name"
  />
</LinearLayout>


 

通知欄繪製在1號LinearLayout中,還是繪製在DecorView中還有待探究。

-----------------

ApiDemo中app包下CustomTitle中自定義TitleBar代碼段

1
2
3
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.custom_title);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_1);


 

載入自定義titleBar後如何查找其中元素呢,其實還是findViewById就可以了,因爲載入的自定義佈局已經在DecorView樹中了

而findViewById是怎麼回事呢。

activity中findViewById源碼

1
2
3
public View findViewById(int id) {
    returngetWindow().findViewById(id);
}


調用了getWindow().findViewById,getWindow返回的是Window點入查看window中源碼

1
2
3
public View findViewById(int id) {
    returngetDecorView().findViewById(id);
}


所以最終是從DecorView最頂層開始搜索的。


理解Window和WindowManager

Activity-->WindowManager-->WindowManagerGlobal-->ViewRootImpl-->WindowSession(Binder)-->WMS



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