Android資源應用

對資源應用做了一些學習,準備從三個方面來描述總結:

1. 整體介紹
2. 資源打包
3. 資源配置&加載

1. 整體介紹

1. 資源類型
定義Android資源時,主要有兩個目錄,一個是assets, 另一個是res目錄。
assets目錄用於存放一些原始文件,資源打包後這個目錄下的文件不會被編譯,內部定義的資源也不會分配ID.
res目錄存放的文件則會參與編譯(res/raw除外),都會被分配資源ID.


針對前面提到的兩個目錄下的各種資源,最終都是經過AAPT打包到APK中。資源打包時,會生成R.java,  提供給應用程序通過ID訪問資源。

res目錄下的文件,除了res/raw外的文件都會進行編譯,編譯成二進制文件輸出,這樣會加速後續資源的訪問。

對於res目錄下的資源,由於都分配了ID, 應用程序可以通過資源ID來訪問。而對於assets目錄下的資源,應用程序通過具體的文件名訪問。



1.2 Android顯示相關的概念

Android應用開發提供資源時需要能適配Android設備的多樣性 。對與Android不同的顯示設備,經常使用如下一些概念描述。


分辨率和DP是最常接觸使用的,給定如下一些分辨率與DP轉換示例:

配置1: 1920 x 1080, 480dpi   ==> 640dp x 360dp
配置2: 1280 x 720, 320dpi     ==> 640dp x 360dp
配置3:  960 x 600, 160dpi      ==> 960dp x 600dp
配置4: 1280 x 800,  160dpi    ==> 1280dp x 800dp


2. Android資源打包

Android代碼資源分離,採用AAPT單獨對資源編譯打包
AAPT(Android Asset Packaging Tool)
源碼路徑:frameworks/base/tools/aapt/

2. 1 資源打包生成文件

資源編譯打包後,在APK中有res, assets兩個目錄,同時有resources.arsc資源索引文件。

Res目錄中除了raw目錄,其他文件都是編譯過的,另外values會打包到resources.arsc中, 所以打包後的res中沒有values目錄



Resources.arsc是資源索引文件,可以使用Android Studio直接查看, 或者使用aapt l -a > output導出
資源索引表建立ID與資源值/路徑的映射關係
對於layout/drawable等資源, ID映射的值是一個全路徑文件名。資源查找時,拿到的是一個文件名,Resource Framework會再根據文件名打開對應的文件提供給App


對於string等一些資源,ID映射的直接是一個值 ,因此資源查找時直接獲取到App需要的值。

AssetManager基於索引表查找資源

通過Resource ID加載非asset資源
先通過AssetManager查詢resources.arsc中資源ID對應的值
ID對應的如果是一個值,例如value/string值,直接返給應用
ID對應的如果是一個文件名, 需要再通過AssetManager打開文件
通過文件名加載asset資源
直接通過AssetManager打開文件



資源打包的最後過程會生成R.java,裏面給出了所有資源的ID.

提供給程序指定資源ID獲取到對應資源
ID格式4 Byte: [1][1][2] :  [package][type][index]



3. 資源配置

關於資源配置,Android developer上有詳細的文檔說明:

https://developer.android.google.cn/guide/topics/resources/providing-resources.html

Android定義了18個維度的配置限定符, App通過配置限定符來提供備用資源。
資源定義時需要按表中順序添加限定符,系統加載資源時也是按表中優先級依次適配資源。


3.1 屏幕尺寸Screen Size限定符

此配置符用於爲不同屏幕尺寸提供不同資源
屏幕尺寸: 四種通用尺寸:小、正常、 大 和超大
Android早期版本多用於適配平板所需資源,但區分不夠精確
使用smallest width, available width, available height替代


3.2 屏幕寬度/高度Available Width /Height限定符

w<N>dp (w720dp, w1024dp)
h<N>dp (h720dp, h1024dp)
應用實際可用空間不是物理屏的size, 需要減去系統永久性UI的空間
豎屏切換時, 可用寬/高會發生轉換
系統會使用最接近(但未超出)設備當前屏幕寬度的值
例如系統檢測到當前應用可用屏幕寬度爲720dp, 則優先匹配w720dp, 如果沒有,則查找小於w720dp的配置
Width對layout的影響更大,使用available height的應用相對較少.

3.3 最小寬度Smallest Width限定符

sw<N>dp (sw320dp,w600dp,sw720dp)
Available Width/Heigh中的最小尺寸
不受屏幕旋轉影響
系統會使用最接近(但未超出)設備 smallestWidth 的值

w/h/sw都是應用的configuration, 是Activity實際可用的空間
Freeform模式下,應用窗口大小可以自由縮放,所以在縮放過程中會觸發configuration change, 重新加載適合的資源.

3.4 屏幕像素密度限制符

應用開發時僅僅使用sw/w/h有時候不夠
[1080p 480dpi] 與[720p 320dpi]對應的sw/w/h相同,但可能需要提供不同的圖片資源
應用如果只提供sw<N>dp資源,在小尺寸屏幕或者應用窗口被縮小的情況下,系統可能無法查找到合適的sw限定符資源
sw/w/h沒有反應出屏幕像素密度
引入像素密度限制付: <N>dpi
如果沒有提供最符合當前設備配置的限定符,則系統使用其中最匹配的資源
先大後小的原則匹配 
源碼中的算法:
configuration < low < high ==> 選擇low
configuration > high > low ==> 選擇high
low < configuration < high ==> (2 * low – configuration) * high > configuration * configuration ? : low , high

Android系統會根據物理像素密度設定Android系統的像素密度.


3.5 屏幕分辨率限定符

引入screen size的限制符: <N>x<M>
value-1920x1080
適配原則
匹配最接近(但未超出)設備分辨率的值
源碼中匹配算法:
去除超出screen size的資源
使用(w+h)最接近當前configuration.(w+h)的資源
screen size與available width/height的比值爲dpi/160

3.6 限定符組合使用

很多場景需要使用多種限定符的組合來提供合理的資源,如下是隨意列舉的一些配置:
w+h:values-w720dp-h400dp; 
sw + dpi:values-sw400dp-xxdpi; 
dpi + screen size:values-xxhdpi-1920x1080

4. 資源加載實例

4.1 Layout資源加載

加載原則
1. 按Android定義的18個維度按優先級匹配
2. 某一個維度內,則按當前維度的規則
swxxxdp
優先找最匹配的,然後找低於configuration的swxxxdp
不會匹配高於當前configuration的swxxxdp
Density
優先找最匹配的
然後按先大後小的原則匹配 

給定一個配置:1920x1080, 屏幕密度:480dpi,  給定如下一些layout,則加載的優先級如下:
layout-sw360dp
layout-sw240dp
layout-xxhdpi
Layout-xxxhdpi
layout-xhdpi
layout-hdpi
layout-mdpi

4.2 Drawable資源加載

與Layout相同的加載原則:先高後低
假設設備xxhdpi:匹配優先順序爲xxhdpi > xxxhdpi> xhdpi> hdpi> mdpi
爲了保證視覺一致性,系統會再對圖片按比例進行縮放處理
假設設備xxhdpi, 在drawable-mdpi找到圖片,系統認爲你放在mdpi下的圖片可能偏小,所以做了自動放大處理. 放大的倍數爲DPI的比值
此例會放大480/160 = 3倍
影響顯示效果, 佔用內存增大
同樣,如果在drawable-xxxdpi找到圖片,系統認爲圖片偏大,所以自動縮小.
縮小480/640 = 0.75

給定設備:1920x1080, 480dpi. 提供圖片:270 x 480 (屏幕1/4),放置在如下不同drawable-xxx目錄(xxxhdip ,  xxhdpi,  xhdpi, mdpi),將得到不同縮放的視覺效果:


如何保證Drawable的視覺一致性

如果提供多套資源,圖片需要遵循縮放比率


如果提供一套資源,儘量提供高密度的資源
圖片放大比圖片縮小的視覺效果差

4.3 Values目錄

其中有dimen等一些與屏幕顯示相關的配置
values目錄下一般是使用dp進行定義,已經保證了視覺一致性,所以系統不會進行縮放
某些場景希望視覺尺寸不同,則增加values-xxx目錄定義新的值.例如物理尺寸大的平板需要更大的UI顯示


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