前面一篇大致介紹如何裝載各種資源到系統路徑下,下面看看如何獲取這些資源.
做每一個Activity時,不可或缺的需要設置一個佈局,後者一個View來顯示給用戶.
public void setContentView(int layoutResID)
以及:
public void setContentView(View view)
都比較常見.
先看第一種:
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initActionBar();
}
程序的通過getWindow...直接將資源ID交給了Window類去處理,後面的initActivityBar在Activity創建的時候就獲取的Actionbar的樣式,參考前面的Activity圖形化生成的博文.下面繼續看看Window是如何處理資源的:打開PhoneWindow.java
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
一看,和前面Activity的圖形化生成有的一拼,這個地方我們只關注資源是如何解析獲取的.
mLayoutInflater.inflate(layoutResID, mContentParent);
這個就是LayoutInflater類,這個類應該很熟悉,經常在一些彈出框界面顯示View的時候使用.
轉到LayoutInflate類中:
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
if (DEBUG) System.out.println("INFLATING from resource: " + resource);
XmlResourceParser parser = getContext().getResources().getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
這裏面不再去介紹上面方法中的inflate(....)是如何將各自的view添加到root中了.
只看資源解析:
XmlResourceParser parser = getContext().getResources().getLayout(resource);
然後繼續跟蹤:
public XmlResourceParser getLayout(int id) throws NotFoundException {
return loadXmlResourceParser(id, "layout");
}
就到了Resource.java類中:
/*package*/ XmlResourceParser loadXmlResourceParser(int id, String type)
throws NotFoundException {
synchronized (mTmpValue) {
TypedValue value = mTmpValue;
getValue(id, value, true);
if (value.type == TypedValue.TYPE_STRING) {
return loadXmlResourceParser(value.string.toString(), id,
value.assetCookie, type);
}
throw new NotFoundException(
"Resource ID #0x" + Integer.toHexString(id) + " type #0x"
+ Integer.toHexString(value.type) + " is not valid");
}
}
繼續看getValue方法:
public void getValue(int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
if (found) {
return;
}
throw new NotFoundException("Resource ID #0x"
+ Integer.toHexString(id));
}
看到mAssets.getResourceValue,就到了AssetManager管理器了,到jni層,跳過一些過度的類,這個類就跳過,直接看ResourceType.cpp
ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, uint16_t density,
uint32_t* outSpecFlags, ResTable_config* outConfig)
在這個方法裏面,都是由下面這一句展開的.這個地方或
const ssize_t p = getResourcePackageIndex(resID);
然後根據這個得到:
const PackageGroup* const grp = mPackageGroups[p];
獲取grp對象後,由於每一個package都對應一個PackageGroup,輪詢查找,通過ResourceIDmap獲取對應的資源rc返回.
這裏面涉及的資源結構體還是相當複雜,雖然很燒腦子,還好還是有牛人給出了具體說明,可以參考下面:
http://blog.csdn.net/luoshengyang/article/details/8744683