天天看點

Android資源管理概述

       我們知道Android系統跑在各種各樣的裝置上,它的運作環境極為複雜,比如不同的語言、不同的螢幕密度、大小和方向等等。為了保證良好的顯示效果,在不同的環境下,我們應該提供不同的資源。但是這些資源該如何打包、組織、加載、管理呢。顯然,把這麼繁重的工作交給各個應用去做很不合适,那将會使得每個Android應用中都充斥着大量的資源适配的代碼,醜陋且重複。為了解決這個問題,Android提供了統一的資源管理架構,我們隻要按照架構的約定來組織資源,就可以實作在不寫一行資源适配代碼的情況下,完成資源适配的任務。 還有就是現在比較流行的動态加載、熱修複、元件化等技術,都繞不開資源這個子產品。是以,打算深入了解一下Android的資源管理機制。

       Android資源管理子產品的主要功能包括對資源的分類、組織、編譯、打包、加載、引用等。這些功能主要分布在AAPT和AssetManager兩個module中。AAPT負責資源的組織、編譯、打包這些工作,而資源的加載和引用則主要由AssetManager來實作。

       Android資源的總體來說可以分為兩大類:Assets和res。

       Assets類型的資源,AAPT在編譯打包的時候不會對它做任何的處理,當然也不會為它生成資源ID,我們要通路Assets類型的資源也就隻能以檔案名的方式來通路。

       res類型的資源,AAPT在編譯的時候,會為它配置設定資源ID,我們通路的時候可以通過資源ID來通路。當然,也可以通過資源名稱來通路,但是Android并不推薦這樣做,因為這樣要周遊整個key StringPool,并且對每個字元串做比較,效率極低。這裡多說一句,所謂的資源ID,也就是我們經常使用的的R檔案的本質是資源的一個索引。使用索引來通路,效率當然比周遊查詢要高太多了。

       在res類型的資源當中,有一種raw類型的資源,AAPT除了為它生成資源ID外,也不會對它做特殊處理,類似的還有圖檔資源。其餘的資源又可以分為XML類型的,比如:layout、drawable、anim、menu、xml等;還有values類型的,比如:string、integer、dimen、color等。在編譯的時候,AAPT會将XML類型的資源編譯成二進制的形式,建立字元串池,這樣做的好處有很多,比如可以節約空間,在xml檔案中android這個namespace會引用非常多次,但在字元串池裡,隻有一次;比如可以加快解析速度,因為它是基于索引的,而不是基于字元串比較的。

       對于values類型的資源,比如string、interger等,AAPT會直接把他們編譯入Global String Pool,這也就是我們解壓APK後,看不到res/values/目錄的原因了。

       總結起來就是,AAPT會對不同的資源類型做不同程度的處理,以達到節約空間,節省時間的目的。

       資源的組織,大家都比較熟悉了,對于不同的config,建立不同的目錄,提供不同的資源,如想更加詳細地了解,大家可以參考老羅的文章。

        資源的編譯,這是AAPT的重頭戲,主要包括了,對values資源的編譯、對XML資源的編譯(包括AndroidManifest.xml)、R檔案的生成,.d(依賴檔案)的生成、resources.arsc(資源索引表)的生成等。另外,我們還會重點讨論這些過程中涉及到的一些不常見的概念及其相關處理過程,比如overlayPackage、Bag資源、privateSymbolPackage、Res_lib等。其實,一般情況下,Android源生的AAPT足以滿足我們對應用資源的編譯需求,當我們需要定制自己的系統資源的時候才可能涉及到對AAPT的修改。不過,需求是多種多樣的,多了解其原理和代碼,沒準兒哪天就派上用場了呢。

        資源的加載和引用,則是由AssetManager來完成的。當Zygote創鍵完虛拟機,進入java世界後,fork出其它子程序前,它會加載許多系統的東西,系統資源也會在這個時候被加載。當這些資源被加載後,它們會被緩存起來,當需要再次引用時,就可以不用重新創鍵了。其實,fork出來的每一個子程序,都是已經加載過系統資源的了。這部分代碼在framework/base/core/java/com/android/internal/os/ZygeteInit.java中:

Android資源管理概述

        其中,mResources = Resources.getSystem();這行代碼會通過AssetManager來加載系統的資源,具體就不在這裡詳述了,後面我們會有文章專門讨論。在讨論AssetManager的過程中,我們會也會講一些不常用的概念和機制,比如OverlayPackage的加載機制、Idmap、DynamicReference、Theme的實作等。