android中Resources的资源缓存机制
来源:互联网 发布:遗传算法的过程 编辑:程序博客网 时间:2024/05/20 05:26
通过梳理下ImageView的setImageResource方法的调用流程,来看下android中Resources的资源缓存机制。
public void setImageResource(int resId) { // The resource configuration may have changed, so we should always // try to load the resource even if the resId hasn't changed. final int oldWidth = mDrawableWidth; final int oldHeight = mDrawableHeight; updateDrawable(null); mResource = resId; mUri = null; resolveUri(); if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) { requestLayout(); } invalidate(); }先调用updateDrawable将mDrawable置为null,然后调用resolveUri方法。
private void resolveUri() { ... ... if (mResource != 0) { try { d = mContext.getDrawable(mResource); } catch (Exception e) { Log.w("ImageView", "Unable to find resource: " + mResource, e); // Don't try again. mUri = null; } } else if (mUri != null) { ... ... } else { ... ... } else { return; } updateDrawable(d); }resolveUri中会调用Context的getDrawable方法。
public final Drawable getDrawable(int id) { return getResources().getDrawable(id, getTheme()); }Context的getDrawable方法会间接调用Resources的getDrawable方法。
public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException { TypedValue value; synchronized (mAccessLock) { value = mTmpValue; if (value == null) { value = new TypedValue(); } else { mTmpValue = null; } getValue(id, value, true); } final Drawable res = loadDrawable(value, id, theme); synchronized (mAccessLock) { if (mTmpValue == null) { mTmpValue = value; } } return res; }最后会调用到Resources的loadDrawable方法,在看loadDrawable方法的具体流程之前,先看下Resources中用于缓存的相关数据结构。
// Information about preloaded resources. Note that they are not // protected by a lock, because while preloading in zygote we are all // single-threaded, and after that these are immutable. private static final LongSparseArray<ConstantState>[] sPreloadedDrawables; private static final LongSparseArray<ConstantState> sPreloadedColorDrawables = new LongSparseArray<ConstantState>(); private static final LongSparseArray<ColorStateList> sPreloadedColorStateLists = new LongSparseArray<ColorStateList>();上面的数据结构是在zygote进程中预加载的,因为是无法改变的,所以没有加锁保护。
private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mDrawableCache = new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>(); private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mColorDrawableCache = new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>(); private final LongSparseArray<WeakReference<ColorStateList>> mColorStateListCache = new LongSparseArray<WeakReference<ColorStateList>>(); private final ConfigurationBoundResourceCache<Animator> mAnimatorCache = new ConfigurationBoundResourceCache<Animator>(this); private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache = new ConfigurationBoundResourceCache<StateListAnimator>(this);上面的数据结构分别用来缓存不同类型的资源,下面来看下loadDrawable的具体流程。
Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException { ... ... final boolean isColorDrawable; final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches; final long key; if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { isColorDrawable = true; caches = mColorDrawableCache; key = value.data; } else { isColorDrawable = false; caches = mDrawableCache; key = (((long) value.assetCookie) << 32) | value.data; } // First, check whether we have a cached version of this drawable // that was inflated against the specified theme. if (!mPreloading) { final Drawable cachedDrawable = getCachedDrawable(caches, key, theme); if (cachedDrawable != null) { return cachedDrawable; } } // Next, check preloaded drawables. These are unthemed but may have themeable attributes. final ConstantState cs; if (isColorDrawable) { cs = sPreloadedColorDrawables.get(key); } else { cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key); } final Drawable dr; if (cs != null) { final Drawable clonedDr = cs.newDrawable(this); if (theme != null) { dr = clonedDr.mutate(); dr.applyTheme(theme); dr.clearMutated(); } else { dr = clonedDr; } } else if (isColorDrawable) { dr = new ColorDrawable(value.data); } else { dr = loadDrawableForCookie(value, id, theme); } // If we were able to obtain a drawable, store it in the appropriate // cache (either preload or themed). if (dr != null) { dr.setChangingConfigurations(value.changingConfigurations); cacheDrawable(value, theme, isColorDrawable, caches, key, dr); } return dr; }在loadDrawable方法中,首先会判断资源类型,根据不同的资源类型来查询不同的资源缓存数据结构,会依次调用getCachedDrawable,getCachedDrawableLocked,getConstantStateLocked来查询缓存,这些方法这里不详述。如果命中了缓存,则直接返回缓存;如果没有命中缓存,则先查询预加载的资源缓存,如果也没有命中,新建一个Drawable对象(如果isColorDrawable为true,则新建一个ColorDrawable对象,否则调用loadDrawableForCookie方法,从xml文件中新建Drawable对象),最后调用cacheDrawable方法缓存Drawable对象。
小结:经过上面对ImageView的setImageResource方法调用流程的梳理,简要地介绍了下android中Resources的缓存机制,不足之处希望大家指正。
0 0
- android中Resources的资源缓存机制
- android 中对Resources资源的访问
- Android中WebView的缓存机制 & 资源预加载方案
- [工具]android-unused-resources 找出项目中没用的资源
- Android 代码中 引用资源本身Resources
- Android WebView 的缓存机制 & 资源预加载方案
- 关于web开发中静态资源缓存机制的总结
- Android资源访问机制——获取Resources对象
- Android资源访问机制—获取Resources对象
- Android资源访问机制——获取Resources对象
- Android资源访问机制—获取Resources对象
- 【Android】Application Resources 应用程序的资源
- Android中图片的三级缓存机制
- android之resources资源
- Android:Resources资源文件
- Android 资源(Resources)访问
- android缓存的机制
- Android:手把手教你构建 Android WebView 的缓存机制 & 资源预加载方案
- C. Timofey and a tree codeforces 395 div2 C
- iOS10新特性
- 有趣的婚姻,要互相调戏
- Git的详细教程(附总结的常用代码)
- 大前端时代到来,你可以改变世界--系列公开课
- android中Resources的资源缓存机制
- wikioi1230 元素查找
- 关于使用ajaxSubmit来上传图片
- linux下调用openssl实现获得文件MD5值
- SQLServer2005删除log文件和清空日志的方案
- No mapping found for HTTP request with URI [...] in DispatcherServlet with name '...'
- FINDBUGS错误: OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE
- LEETCODE--Minimum Moves to Equal Array Elements
- 算法提高 棋盘多项式