前兩年剛?cè)肼毜臅r候牍蜂,有時間研究了下Android資源問題吏饿,這兩天回頭再看的時候磁玉,發(fā)現(xiàn)很多東西都忘得差不多了榛瓮。這里重新整理下之前的內(nèi)容颜启,也將之前發(fā)在公司內(nèi)部的文章同步到這里來远寸。
在Android應(yīng)用程序開發(fā)過程中硫痰,一般都會通過R..方式引用具體資源觉至,但該方式是如何查找到具體資源的呢璧尸?R.java文件又是如何生成的呢咒林? 該文檔主要參考了老羅的文章,并生成自己的見解爷光,若有錯誤之處垫竞,懇請指正。 詳見:http://blog.csdn.net/luoshengyang/article/details/8744683.
在Android應(yīng)用程序開發(fā)過程中蛀序,一般都會通過R..方式引用具體資源欢瞪,但該方式是如何查找到具體資源的呢?R.java文件又是如何生成的呢徐裸?
1.1遣鼓、首先看下資源編譯與打包的概覽
看完概覽圖后,挑幾步細(xì)致分析一下重贺。
1.2骑祟、第1步:解析AndroidManifest.xml
該步主要是獲得應(yīng)用程序的包名,即通過解析package屬性獲得气笙;再通過獲得到的包名創(chuàng)建資源表ResourceTable次企。那么,什么是ResourceTable呢潜圃?
ResourceTable類定義在ResourceTable.h文件中抒巢,方法實(shí)現(xiàn)在ResourceTable.cpp中。從圖看出ResourceTale結(jié)構(gòu)是一層層包起來的秉犹。
ResourceTable
ResourceTable的重要成員變量有:
mAssetsPackage:當(dāng)前正在編譯的資源包名稱蛉谜。
mPackages:當(dāng)前編譯的資源包稚晚,包括引用的資源包(如系統(tǒng)資源包等)。
mOrderPackages:與mPackages一樣型诚,只是按package Id有小到大順序排列客燕。
mAssets:當(dāng)前編譯的資源目錄,指向一個AaptAssets對象狰贯。
Package
Package用來描述一個包也搓,其重要成員變量有:
mName:包名。
mTypes:包含的資源類型涵紊,每個類型用Type描述傍妒,如layout、drawable等類型摸柄。
mOrderedTypes:與mTypes一樣颤练,只是按Type Id有小到大順序排列。
Type
Type用來描述一個資源類型驱负,其重要成員變量有:
mName:資源類型名稱嗦玖,如layout、drawable等跃脊。
mConfigs:資源配置項(xiàng)列表宇挫,每一系列同名的資源都用一個ConfigList描述,如Type為layout下的main.xml酪术、sub.xml分別對應(yīng)一個ConfigList器瘪。
mOrderedConfigs:與mConfigs一樣,只是按Entry Id有小到大順序排列绘雁。
mUniqueConfigs:表示包含不同的資源配置信息個數(shù)娱局。
ConfigList
ConfigList用來描述一個資源配置項(xiàng)列表,同名的資源保存在同一個ConfigList中咧七,其重要成員變量有:mName:資源項(xiàng)名稱衰齐。
- mEntries:包含的資源項(xiàng),Entry列表继阻。如耻涛,圖上icon.png對應(yīng)三種不同的配置:hdpi/mdpi/ldpi,那以icon.png為名稱ConfigList就對應(yīng)三個Entry瘟檩。
Entry
Entry用來描述一個資源項(xiàng)抹缕,其重要成員變量有:
mName:資源項(xiàng)名稱。
mItem:資源項(xiàng)數(shù)據(jù)墨辛,用Item描述卓研。
Item表示資源項(xiàng)數(shù)據(jù),其重要成員變量有:
values:資源項(xiàng)原始值,是一個字符串奏赘。
parsedValue:values解析后的資源值寥闪。如果values為“123”,那parsedValue為大小為123的整形數(shù)據(jù)。
1.3磨淌、第3步:收集資源文件
該步將收集的資源文件保存到AaptAssets中疲憋,看下AaptAssets:
mPackage:當(dāng)前編譯包名
mRes:資源類型集,收集的資源文件保存在mRes中梁只。
mHaveIncludedAssets:是否有引用包
mIncludedAssets:用來解析引用包
-
mOverlay:當(dāng)前編譯資源的重疊包
舉個例子缚柳,看下mRes是如何保存資源文件的,假設(shè)工程資源目錄如下所示:
那mRes中保存的資源文件如下所示:
由上圖可以看出搪锣,每種資源對應(yīng)一個ResourceTypeSet對象秋忙,而ResourceTypeSet可看成是按名稱保存的AaptGroup集合;而AaptGroup保存了相同文件名下不同配置的文件构舟。
1.4灰追、第4步:收集資源文件添加到ResourceTable
仍以下圖為例,注意該步values資源需編譯后再添加旁壮。
由于values需編譯后添加监嗜,所以在該步中值包含兩種類型資源:drawable谐檀、layout抡谐,用Type描述。添加完后桐猬,ResourceTable保存的信息:
-
drawable的Type有一個ConfgList:icon.png
該ConfigList有3個Entry:res/drawable-ldpi/icon.png麦撵、res/drawable/mdpi/icon.png、res/drawable-hdpi/icon.png
每個Entry對應(yīng)一個ConfigDescription溃肪,用來描述不同的資源配置免胃。
-
layout的Type有兩個ConfigList:main.xml、sub.xml
main.xml的configList有一個Entry:res/layout/main.xml
sub.xml的ConfigList有一個Entry:res/layout/sub.xml
1.5惫撰、第5步:編譯values資源
該步完成values資源編譯羔沙,并將編譯后的資源添加到ResourceTable中。 舉個例子厨钻,假設(shè)string.xml內(nèi)容如下所示:
string.xml編譯添加后扼雏,ResourceTable就多了一個名稱為string的Type,該Type有5個ConfigList夯膀。名稱為:“app_name”诗充、“sub_activity”、“start_in_process”诱建、"start_in_new_process"和"finish"蝴蜓,每個ConfigList有一個Entry。
1.6、第9步:生成resources.arsc
該步生成最終的resources.arsc文件茎匠,resources.arsc的主要作用是Resources可以根據(jù)資源ID在該文件中查找到對應(yīng)的資源文件名稱格仲。
對生成的resources.arsc解析,可以得到resources.arsc有三部分構(gòu)成:資源索引表頭部汽抚、字符串資源池抓狭、packages數(shù)據(jù)塊。
展開字符串資源池可以發(fā)現(xiàn)造烁,字符串資源池有字符串資源池頭部否过、字符串索引和字符串?dāng)?shù)據(jù)組成。其中惭蟋,字符串索引指示對應(yīng)的字符串?dāng)?shù)據(jù)在資源池中的開始位置苗桂。
1.7、總結(jié)
通過R..方式查找資源名稱的過程可簡述為:先從R.java文件中找到對應(yīng)的資源ID告组,再通過資源ID在resources.arsc找到對應(yīng)的資源名稱煤伟。關(guān)于根據(jù)資源名稱如何打開資源,后面再分析木缝。