Android資源管理框架

簡介


        Android系統運行在全球各個地區各種各樣的設備上,爲了在不同設備、不同國家不同地區的設備上都保持良好的用戶體驗,必須針對不同的設備不同語言等等差異做資源適配。爲了幫助開發者承擔絕大多數的工作,給開發者一個友好的開發模型,Android系統提供了一套統一的資源管理框架。從實現的層面講,Android的資源管理框架和AMS、Zygote、PMS、ActivityThread、編譯系統等衆多系統核心模塊相關。本文旨在從架構層面去分析Android的資源管理框架的一個概貌。

資源管理框架


        首先,根據我的從源碼的分析和網上資料,我們給出下面這張整體架構圖:

        結合上圖,下面我們介紹一下Android資源管理框架的一些核心概念、模塊和核心處理邏輯。後面的分析中有一些名詞出於自身的理解,可能和網上其他資料介紹的不一樣。

資源載體

        資源的載體在Android資源管理框架中,按我的理解分爲如下幾種:res,resource.arsc,R.java,資源加載到內存後的數據結構。

        res - res目錄下的各種xml文件、圖片等,這些是開發人員提供的原始資源格式,res目錄下raw格式、圖片以及xml類型的資源會打包到apk包中,values類型的資源在apk包中則是找不到的,因爲values下的資源被直接打包到了resource.ac這個二進制格式的文件中。

        resource.arsc - 資源索引表,它是由aapt(aapt2)編譯生成的,裏面存儲了一部分資源(values類型的資源,或者叫做簡單資源)和一些複雜資源的信息,主要是一些raw、圖片、xml文件的路徑,和索引信息。資源管理框架可以解析這個二進制文件裏的索引信息,快速定位到資源。

        R.java - 嚴格的講,R.java並不承載資源本身,它裏面只是存儲了一些自動生成的索引,通過這些索引應用程序可以在代碼裏方便的訪問res目錄定義的資源,在運行時,資源管理框架通過應用代碼傳遞的索引信息可以快速從resource.arsc或者緩存中找到資源。

        資源加載到內存後的數據結構 - AMS將一個app的進程拉起來的過程中,在app進程成初始化的時候,資源管理框架會去加載apk包中的資源信息,也就是加載resource.arsc,會把加載的信息用一系列的數據結構去描述,這些數據結構和邏輯主要集中在Native層的資源管理框架中。另外系統資源framework-res.apk會在Zygote啓動的過程中預加載,這樣每個app進程在被fork出來之後就可以直接使用了,這樣可以加速應用啓動速度。

AAPT&AAPT2

        AAPT2是一個資源預編譯工具。Android Studio和Android Gradle插件使用它來編譯和打包應用程序的資源,當然aosp系統也是通過它來打包系統資源framework-res.apk的。AAPT2會解析資源文件,爲資源項生成索引,並生成R.java文件和resource.arsc。AAPT是AAPT2的早期版本,這兩個工具的源碼位於framework/base/tools目錄下。

系統資源

        Android的資源管理框架不止管理着apk本身的資源,它還管理着一類重要的資源,那就是系統資源,也就是我們平常在做app開發時通過@android:引用的資源。Android的系統資源存儲在一個特殊的apk中,framework-res.apk。framework-res.apk在Zygote進程啓動時會被預加載,這樣應用進程在被Zygote fork出來的時候,系統資源就可以使用了,而不需要去做加載,這樣做的一個好處就是提升了引用冷啓動的速度。

apk資源加載

        在Android四大組件(activity、service、broadcast receiver、content provider)啓動時,AMS會通過Zygote fork出承載四大組件運行的客戶端進程,客戶端進程的管理者就是我們熟悉的ActivityThread。在客戶端啓動的過程中,ActivityThread會通過ResourceManager.getTopLevelResources()方法創建出AssetManager對象,AssetManager對象通過JNI調用native層的AssetMnager對象加載apk的資源索引表,另外也會加載Overlay包和共享資源股的資源索引表。

Configuration

        Android資源管理框架解決了兩個問題:1. 資源的快速訪問;2. 解決不同設備資源適配問題。當不同配置的情況下,我們的程序通過索引拿到的真實資源是不一樣的。那麼配置是在哪裏,又是怎麼生效的呢?在Android系統中,靜態配置信息是在framework/base/core/java/android/content/res/Configuration.java中配置的,另外一些動態配置,比如橫豎屏、語言選擇等,則受到sensor事件,用戶設置得影響,配置改變知乎系統會刷新資源管理對象的配置信息,並刷新顯示。

高級話題


        關於資源管理框架的高級話題有兩個,Overlay和共享資源庫。

Overylay

        當我們從手機主題市場下載主題應用到我們的手機之後,我們手機桌面上的圖標、配色什麼的都改變了,它背後的原理是把手機中程序原本的資源id映射到了主題包中的資源。Overylay就是android原生技術實現這一效果的方式。Overylay是由sony在Android5.0上位AOSP提供的,全稱是Runtime Resources Overlay。Overylay功能是Android資源管理框架能力的一部分,它的基本原理如下:

        1. 首先android提供了overylay標籤來支持Overylay包替換目標(Target)包的資源;

        2. 將Overylay包拷貝到固定的目錄下,由PMS在包掃描階段提取對應的Overylay包的Target包的信息,並通過local socket請求installd做idmap,這樣建立Overylay包和Target包的資源映射,並且PMS會把Overylay包的路徑寫入到Target包的Applicationinfo信息中去;

        3. 應用進程在初始化的過程中,除了加載apk本身的資源包之外,還會加載所有的Overylay包的資源並且會加載idmap信息;

        4. 當應用銅鼓資源id獲取某項資源時,資源管理框架會查找idmap信息中是否有該項資源的映射關係,存在的話有優先返回Overylay包中對應的資源。

共享資源庫

        Adnroid的共享資源庫在概念上有些類似於程序開發中的so庫。在AndroidManifest中通過uses-library標籤我們就能在應用程序中引用共享資源庫裏的資源了。添加了這個標籤之後,在應用程序初始化時,調用PMS獲取ApplicationInfo,PMS會把共享資源庫包的路徑寫入到ApplicationInfo中去。這樣在ActivityThread通過AssetManager對象加載客戶端進程資源的時候也會把共享庫包中的資源加載進進程空間中。這樣,我們在程序中引用共享資源庫中資源就能得到正確加載。

總結


        Android系統爲不同設備的資源適配問題和資源快速訪問問題提供了一套貫穿編譯系統-APP構建-Framework-Native的資源管理框架。它使用二進制格式的資源索引表,既提高了訪問速度,又節約了空間,並且還提供了Runtime Resources Overlay和共享資源庫等高級特性,這些使得Android資源管理框架可以高效靈活的滿足衆多場景開發需求,比如主題換膚等等。本文通過自己的理解和網上查閱資料,高度概括了自己對Android資源管理框架的理解。這裏推薦一個博客,裏面對Android資源管理框架做了詳細的源碼分析,也感謝博主,https://me.csdn.net/dayong198866.

 

 

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