天天看點

Android什麼時候進行View中Background的加載

對大多數android的開發者來說,最經常的操作莫過于對界面進行布局,view中背景圖檔的加載是最經常做的。但是我們很少關注這個過程,這篇文章主要解析view中背景圖檔加載的流程。了解view中背景圖檔的加載(資源的加載)可以讓我們對資源加載的過程進行一些優化,另外當需要進行整個應用的換膚時,也可以更得心應手。

view圖檔的加載,我們最常見的就是通過在xml檔案當中進行drawable的設定,然後讓android系統幫我們完成,或者手動寫代碼加載成bitmap,然後加載到view上。這篇文章主要分析android在什麼時候以及怎麼幫我們完成背景圖檔的加載的,那麼我們就從activity.setcontentview還是layoutinflater.inflate(...)方法開始分析。

上面這麼長一串代碼,其實思路很清晰,就是針對xml檔案進行解析,然後根據xml解析出的每一個節點進行view的初始化,緊接着将view的layout參數設定到view上,然後将view添加到它的父控件上。

為了了解view是怎麼被加載出來的,我們隻需要了解

跟進去看看。

上面代碼的重點在于try...catch裡的内容。try包起來的東西就是對view進行初始化,注意到上面代碼中有幾個factory,這些factory可以在view進行初始化,也就是說其實我們可以在這裡幹預view的初始化。從上面代碼我們可以知道,如果我們自定義了一個factory,那麼目前要初始化的view會優先被我們自定義的factory初始化,而不通過系統預設的factory初始化。那麼如果我們要自定義factory,應該在哪裡定義呢?容易想到,factory必須要趕在資源加載前自定義完成,是以我們應該在oncreate(...)的this.setcontentview(...)之前設定layoutinflater.factory。

接下來我們看到上面函數裡面的

這段函數就是對view進行初始化,有兩種情況,一種是系統自帶的view,它在

這裡面進行初始化,因為如果是系統自帶的view,傳入的那麼一般不帶系統的字首"android.view."。另一個分支初始化的是我們自定義的view。我們跟進oncreateview看看。

從oncreateview(...)中我們知道,其實createviewfromtag(...)中對view的初始化最終都是通過createview(...)這個函數進行初始化的,不同隻在于系統控件需要通過oncreateview(...)加上字首,以便類加載器(classloader)正确地通過類所在的包初始化這個類。createview(...)這個函數的思路很清晰,不看catch裡面的内容,try裡面開頭的兩個分支就是用來将所要用的類構造函數提取出來,android系統會對使用過的類構造函數進行緩存,因為像textview這些常用的控件可能會被使用很多次。接下來,就是通過類構造函數對view進行初始化了。我們注意到傳入構造函數的mconstructorargs是一個包含兩個元素的數組。

那麼我們就很清楚了,它就是調用系統控件中對應兩個參數的構造函數。為了友善,我們就從最基礎的view進行分析。

由于我們隻關注view中的背景圖是怎麼加載的,注意這個函數其實就是周遊attributeset attrs這個東西,然後對view的各個屬性進行初始化。我們直接進入

這裡看看(typedarray.getdrawable)。

我們發現它調用mresources.loaddrawable(...),進去看看。

就是這個函數了,所有view的背景的加載都在這裡了。這個函數的邏輯就比較複雜了,大體說來就是根據背景的類型(純顔色、定義在xml檔案中的,或者是一張靜态的背景),如果緩存裡面有,就直接用緩存裡的。

總結一下,經過上面的分析,我們知道了,android就是在activity.setcontentview(...)中為我們進行資源檔案的加載,精确到具體的函數的話,資源檔案的加載就是在每一個被初始化的view的構造函數中進行加載的。

本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

轉載:http://www.cnblogs.com/kissazi2/p/4310055.html

繼續閱讀