正文
XmlResourceParser其实就包含了xml文件信息的一个对象,之后通过XmlResourceParser将tag的信息取出,递归创建View,具体XmlResourceParser对象的创建如下,
public XmlResourceParser getLayout(int id) throws NotFoundException { return loadXmlResourceParser(id, "layout");}
注意这里解析的xml文件是layout,
XmlResourceParser loadXmlResourceParser(int id, String type) throws NotFoundException { synchronized (mAccessLock) { TypedValue value = mTmpValue; if (value == null) { mTmpValue = value = new TypedValue(); } getValue(id, value, true); if (value.type == TypedValue.TYPE_STRING) { return loadXmlResourceParser(value.string.toString(), id, value.assetCookie, type); } }}
TypedValue是与xml定义的资源对应的值,xml是固定的,非动态的,因此只需要一份,所以可以有缓存机制,看一下getValue如何获取对应xml资源:
public void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException { boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);}
这里牵扯到Android的资源管理内容,mAssets是一个AssetManager对象,
final boolean getResourceValue(int ident,int density, TypedValue outValue, boolean resolveRefs) { <!--加载资源--> int block = loadResourceValue(ident, (short) density, outValue, resolveRefs); if (block >= 0) { if (outValue.type != TypedValue.TYPE_STRING) { return true; } outValue.string = mStringBlocks[block].get(outValue.data); return true; } return false; }
AssetManager进而会通过native函数加载xml文件信息,
static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz, jint ident,jshort density,jobject outValue,jboolean resolve){ ... AssetManager* am = assetManagerForJavaObject(env, clazz); const ResTable& res(am->getResources()); Res_value value; ResTable_config config; uint32_t typeSpecFlags; ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config); ... uint32_t ref = ident; if (resolve) { block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config); ... } return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config) : block;}
以上代码就是如何获取资源的, 其中res.getResource并不是是每次都加载一遍,第一次加载后就能获得单利ResTable,后面用的都是这个缓存,只不过ResTable不会缓存全部资源,对于布局、图像资源等,缓存的都是引用,所以,如果是真实资源的引用话,还需要通过res.resolveReference来解析真正的资源。资源加载不是这里重点,重点是LayoutInflater如何创建View树,只简单看一下资源加载: