您的位置:首页 > 移动开发 > Android开发

Android AssetManager 简读<2>

2016-04-27 20:00 459 查看
前面一篇大致介绍如何装载各种资源到系统路径下,下面看看如何获取这些资源.

做每一个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返回.

这里面涉及的资源结构体还是相当复杂,虽然很烧脑子,还好还是有牛人给出了具体说明,可以参考下面:

/article/1363495.html


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: