Android LayoutInflater inflate方法效率
16lz
2021-01-23
很多Android开发可能知道, LayoutInflater.inflate()方法是个耗时操作, 应尽量避免调用.
我也曾经非常担心在Adapter和ViewGroup动态循环添加View时耗时太多, 但是感觉Android应该会有个布局xml的解析缓存, 今天看了下Android的源码, 果然如此. 在第一次调用inflate相应布局xml时会比较耗时, 之后就会很快!
下面贴上核心源码:
1. 在LayoutInflater中: public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) { final Resources res = getContext().getResources(); if (DEBUG) { Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" + Integer.toHexString(resource) + ")"); } // 获取布局xml的parser final XmlResourceParser parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { parser.close(); } }
2. 在Resources中: @NonNull XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type) throws NotFoundException { final TypedValue value = obtainTempTypedValue(); try {
3. 在ResourcesImpl中, 首先读取缓存, 如果缓存中不存在, 再去实际读取文件, 解析加载 @NonNull XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id, int assetCookie, @NonNull String type) throws NotFoundException { if (id != 0) { try { synchronized (mCachedXmlBlocks) { final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies; final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles; final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks; // First see if this block is in our cache. final int num = cachedXmlBlockFiles.length; for (int i = 0; i < num; i++) { if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null && cachedXmlBlockFiles[i].equals(file)) { // 已经由缓存, 返回缓存 return cachedXmlBlocks[i].newParser(); } } // 没缓存, 解析加载 // Not in the cache, create a new block and put it at // the next slot in the cache. final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file); if (block != null) { final int pos = (mLastCachedXmlBlockIndex + 1) % num; mLastCachedXmlBlockIndex = pos; final XmlBlock oldBlock = cachedXmlBlocks[pos]; if (oldBlock != null) { oldBlock.close(); } cachedXmlBlockCookies[pos] = assetCookie; cachedXmlBlockFiles[pos] = file; cachedXmlBlocks[pos] = block; return block.newParser(); } } } catch (Exception e) { final NotFoundException rnf = new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id)); rnf.initCause(e); throw rnf; } } throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id)); }
final ResourcesImpl impl = mResourcesImpl; impl.getValue(id, value, true); if (value.type == TypedValue.TYPE_STRING) { // 用ResourcesImpl 实际获取布局xml的Parser return impl.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"); } finally { releaseTempTypedValue(value); } }
更多相关文章
- android 4.04的应用程序启动过程及与Zygote的交互(基于静态源码分
- Unexpected namespace prefix "xmlns" found for tag LinearLayo
- 下载Android Sdk源码方法
- android在布局中动态增加view时的层级控制
- Android 总结:打造Android中的流式布局和热门标签(源码有详细注释)
- Android源码笔记--Activity的启动过程
- android RecyclerView布局真的只是那么简单!
- 【Android系统源码修改】在系统设置中添加设置选项