专栏名称: 刘望舒
腾讯云最具价值专家
目录
相关文章推荐
复利大王  ·  老同学中捞一捞能不能找到免费P友 ·  21 小时前  
复利大王  ·  不讲武德!中x银行? ·  21 小时前  
鸿洋  ·  务必立即拿下软考证(政策红利) ·  昨天  
复利大王  ·  冷暴力女王,翻车了 ·  昨天  
51好读  ›  专栏  ›  刘望舒

LayoutInflater 布局渲染工具原理分析

刘望舒  · 掘金  · android  · 2018-02-01 11:19

正文

请到「今天看啥」查看全文


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树,只简单看一下资源加载:







请到「今天看啥」查看全文