首先看Resources.java中的getDrawable(int id)方法的源码:
public Drawable getDrawable(int id) throws NotFoundException {
synchronized (mTmpValue) {
TypedValue value = mTmpValue;
getValue(id, value, true);
return loadDrawable(value, id);
}
}
在这个方法中找到传入的id的值的图片并返回.
在这里我们可以看到该方法将id传给loadDrawable(value, id);同时传递的还有value,显然这个值是很关键的,看看这个值在这里起到怎样的作用
(1)final TypedValue mTmpValue = new TypedValue();
官方文档对这个类的解释:Container for a dynamically typed data value. Primarily used with Resources for holding resource values.
翻译:
一个动态地数据值的容器。 主要被Resouces使用于持有的资源值.我理解为存储数据类型
(2)getValue(id,value,true)
执行这个方法获取该id的资源的属性
public void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException {
boolean found = mAssets.getResourceValue(id, outValue, resolveRefs);
if (found) {
return;
}
throw new NotFoundException("Resource ID #0x"+ Integer.toHexString(id));
}
这里涉及的方法:
final AssetManager mAssets;
mAssets.getResourceValue(id, outValue, resolveRefs);
源码如下:
final boolean getResourceValue(int ident,TypedValue outValue,boolean resolveRefs){
int block = loadResourceValue(ident, outValue, resolveRefs);
if (block >= 0) {
if (outValue.type != TypedValue.TYPE_STRING) {
return true;
}
outValue.string = mStringBlocks[block].get(outValue.data);
return true;
}
return false;
}
涉及方法:
/** Returns true if the resource was found, filling in mRetStringBlock andmRetData. */
private native final int loadResourceValue(int ident, TypedValue outValue,boolean resolve);
我们已经将加载图片的方法到了底层的C代码,从源码的注释,我们可以看到
"如果资源被找到返回true,同时填补mRetStringBlock andmRetData"
也就是通过id号,我们应该已经拿到资源的属性,存放在value内,通过TypedValue中的方法和属性就可以获得我们想要的值.
在前面做了这么多的准备工作后,下面的源码就是我们实现的核心方法了,
Drawable loadDrawable(TypedValue value, int id)throws NotFoundException {
if (TRACE_FOR_PRELOAD) {
// Log only framework resources
if ((id >>> 24) == 0x1) {
final String name = getResourceName(id);
if (name != null) android.util.Log.d("PreloadDrawable", name);
}
}
final long key = (((long) value.assetCookie) << 32) | value.data;
Drawable dr = getCachedDrawable(key);
if (dr != null) {
return dr;
}
Drawable.ConstantState cs = sPreloadedDrawables.get(key);
if (cs != null) {
dr = cs.newDrawable(this);
} else {
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
dr = new ColorDrawable(value.data);
}
if (dr == null) {
if (value.string == null) {//表示无资源
throw new NotFoundException( "Resource is not a Drawable (color or path): " + value);
}
//获取资源的名字
String file = value.string.toString();
if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "
+ value.assetCookie + ": " + file);
if (file.endsWith(".xml")) {//解析xml文件,返回drawable
try {
XmlResourceParser rp = loadXmlResourceParser(
file, id, value.assetCookie, "drawable");
dr = Drawable.createFromXml(this, rp);
rp.close();
} catch (Exception e) {
NotFoundException rnf = new NotFoundException(
"File " + file + " from drawable resource ID #0x"
+ Integer.toHexString(id));
rnf.initCause(e);
throw rnf;
}
} else {
try {//获取外部资源Asset
InputStream is = mAssets.openNonAsset(value.assetCookie, file, AssetManager.ACCESS_STREAMING);
// System.out.println("Opened file " + file + ": " + is);
dr = Drawable.createFromResourceStream(this, value, is, file, null); is.close();
// System.out.println("Created stream: " + dr);
} catch (Exception e) {
NotFoundException rnf = new NotFoundException(
"File " + file + " from drawable resource ID #0x"
+ Integer.toHexString(id));
rnf.initCause(e);
throw rnf;
}
}
}
}
if (dr != null) {
dr.setChangingConfigurations(value.changingConfigurations);
cs = dr.getConstantState();
if (cs != null) {
if (mPreloading) {
sPreloadedDrawables.put(key, cs);
} else {
synchronized (mTmpValue) {
//Log.i(TAG, "Saving cached drawable @ #" +
// Integer.toHexString(key.intValue())
// + " in " + this + ": " + cs); mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
}
}
}
}
return dr;
}
public Drawable getDrawable(int id) throws NotFoundException {
synchronized (mTmpValue) {
TypedValue value = mTmpValue;
getValue(id, value, true);
return loadDrawable(value, id);
}
}
在这个方法中找到传入的id的值的图片并返回.
在这里我们可以看到该方法将id传给loadDrawable(value, id);同时传递的还有value,显然这个值是很关键的,看看这个值在这里起到怎样的作用
(1)final TypedValue mTmpValue = new TypedValue();
官方文档对这个类的解释:Container for a dynamically typed data value. Primarily used with Resources for holding resource values.
翻译:
一个动态地数据值的容器。 主要被Resouces使用于持有的资源值.我理解为存储数据类型
(2)getValue(id,value,true)
执行这个方法获取该id的资源的属性
public void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException {
boolean found = mAssets.getResourceValue(id, outValue, resolveRefs);
if (found) {
return;
}
throw new NotFoundException("Resource ID #0x"+ Integer.toHexString(id));
}
这里涉及的方法:
final AssetManager mAssets;
mAssets.getResourceValue(id, outValue, resolveRefs);
源码如下:
final boolean getResourceValue(int ident,TypedValue outValue,boolean resolveRefs){
int block = loadResourceValue(ident, outValue, resolveRefs);
if (block >= 0) {
if (outValue.type != TypedValue.TYPE_STRING) {
return true;
}
outValue.string = mStringBlocks[block].get(outValue.data);
return true;
}
return false;
}
涉及方法:
/** Returns true if the resource was found, filling in mRetStringBlock andmRetData. */
private native final int loadResourceValue(int ident, TypedValue outValue,boolean resolve);
我们已经将加载图片的方法到了底层的C代码,从源码的注释,我们可以看到
"如果资源被找到返回true,同时填补mRetStringBlock andmRetData"
也就是通过id号,我们应该已经拿到资源的属性,存放在value内,通过TypedValue中的方法和属性就可以获得我们想要的值.
在前面做了这么多的准备工作后,下面的源码就是我们实现的核心方法了,
Drawable loadDrawable(TypedValue value, int id)throws NotFoundException {
if (TRACE_FOR_PRELOAD) {
// Log only framework resources
if ((id >>> 24) == 0x1) {
final String name = getResourceName(id);
if (name != null) android.util.Log.d("PreloadDrawable", name);
}
}
final long key = (((long) value.assetCookie) << 32) | value.data;
Drawable dr = getCachedDrawable(key);
if (dr != null) {
return dr;
}
Drawable.ConstantState cs = sPreloadedDrawables.get(key);
if (cs != null) {
dr = cs.newDrawable(this);
} else {
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
dr = new ColorDrawable(value.data);
}
if (dr == null) {
if (value.string == null) {//表示无资源
throw new NotFoundException( "Resource is not a Drawable (color or path): " + value);
}
//获取资源的名字
String file = value.string.toString();
if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "
+ value.assetCookie + ": " + file);
if (file.endsWith(".xml")) {//解析xml文件,返回drawable
try {
XmlResourceParser rp = loadXmlResourceParser(
file, id, value.assetCookie, "drawable");
dr = Drawable.createFromXml(this, rp);
rp.close();
} catch (Exception e) {
NotFoundException rnf = new NotFoundException(
"File " + file + " from drawable resource ID #0x"
+ Integer.toHexString(id));
rnf.initCause(e);
throw rnf;
}
} else {
try {//获取外部资源Asset
InputStream is = mAssets.openNonAsset(value.assetCookie, file, AssetManager.ACCESS_STREAMING);
// System.out.println("Opened file " + file + ": " + is);
dr = Drawable.createFromResourceStream(this, value, is, file, null); is.close();
// System.out.println("Created stream: " + dr);
} catch (Exception e) {
NotFoundException rnf = new NotFoundException(
"File " + file + " from drawable resource ID #0x"
+ Integer.toHexString(id));
rnf.initCause(e);
throw rnf;
}
}
}
}
if (dr != null) {
dr.setChangingConfigurations(value.changingConfigurations);
cs = dr.getConstantState();
if (cs != null) {
if (mPreloading) {
sPreloadedDrawables.put(key, cs);
} else {
synchronized (mTmpValue) {
//Log.i(TAG, "Saving cached drawable @ #" +
// Integer.toHexString(key.intValue())
// + " in " + this + ": " + cs); mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
}
}
}
}
return dr;
}