作者:彭丑丑
前言
本文将从源码深入剖析 「图片加载」 的过程。
❝
为方便大家理解,源码已作简化处理。
❞
图片资源加载过程
首先我们看下加载图片资源的入口方法:BitmapFactory.decodeResource()
// BitmapFactory.decodeResource()
public static Bitmap decodeResource(Resources res, int id) {
return decodeResource(res, id, null);
}
public static Bitmap decodeResource(Resources res, int id, Options opts) {
// 步骤1:匹配资源 id,打开InputStream
final TypedValue value = new TypedValue();
InputStream is = res.openRawResource(id, value);
// 步骤2:解码资源,返回 Bitmap
return decodeResourceStream(res, value, is, null, opts);
}
所以,图片资源加载主要分为两步,具体如下图:
步骤1:匹配资源 ID
作用
从资源 id(一个 int 值)定位到具体某一个文件夹下的资源,即**「获得 InputStream和TypedValue(即带有文件夹对应的 densityDpi)」**。
源码解析
// 步骤说明
public static Bitmap decodeResource(Resources res, int id, Options opts) {
// 步骤1:匹配资源 id,打开InputStream -> 关注1
final TypedValue value = new TypedValue();
InputStream is = res.openRawResource(id, value);
// 步骤2:解码资源,返回 Bitmap
return decodeResourceStream(res, value, is, null, opts);
}
/**
* 关注1:ResourcesImpl.openRawResource()
*/
InputStream openRawResource(@RawRes int id, TypedValue value) {
// 匹配资源 -> 关注2
getValue(id, value, true);
// 打开输入流
return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
AssetManager.ACCESS_STREAMING);
}
/**
* 关注2:getValue()
*/
void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs) {
// 查找资源Id & 相关信息存储在 outValue -> 关注3
boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
...
}
/**
* 关注3:AssetManager.getResourceValue()
*/
boolean getResourceValue(@AnyRes int resId, int densityDpi, TypedValue outValue, boolean resolveRefs) {
// 从Native文件中查找 -> 关注4
final int cookie = nativeGetResourceValue(mObject, resId, (short) densityDpi, outValue, resolveRefs);
if (cookie <= 0) {
return false;
}
return true;
}
/**
* 关注4:AssetManager.NativeGetResourceValue()
*/
s