有些时候需要将res中的资源文件加载进来然后做一些修改,然后再赋值给控件使用,比如这样:
Drawable drawable = getResources().getDrawable(int id);
现在我需要把资源文件id所对应的Drawable对象加载进来,然后做向下转型处理,如果我不调试查看本身的类型的话,该怎么知道它到底是哪种类型呢?我们来通过源代码查看究竟:
首先我们找到getResources().getDrawable()方法:
public Drawable getDrawable(int id) throws NotFoundException {synchronized (mTmpValue) {TypedValue value = mTmpValue;getValue(id, value, true);return loadDrawable(value, id);}}
这个方法并没有做什么,进入到loadDrawable方法中:
/*package*/ Drawable loadDrawable(TypedValue value, int id)throws NotFoundException {if (TRACE_FOR_PRELOAD) {// Log only framework resourcesif ((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")) {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 {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;}
这一大段我们看主要的:
if (file.endsWith(".xml")) {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;}}
这里以selector说明,selector是定义在xml中的,我们就找到这个地方,它原来是使用XmlResourceParser来对xml资源文件进行解析的,咱们进去createFromXml方法内部一探究竟:
/*** Create a drawable from an XML document. For more information on how to* create resources in XML, see* <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.*/public static Drawable createFromXml(Resources r, XmlPullParser parser)throws XmlPullParserException, IOException {AttributeSet attrs = Xml.asAttributeSet(parser);int type;while ((type=parser.next()) != XmlPullParser.START_TAG &&type != XmlPullParser.END_DOCUMENT) {// Empty loop}if (type != XmlPullParser.START_TAG) {throw new XmlPullParserException("No start tag found");}Drawable drawable = createFromXmlInner(r, parser, attrs);if (drawable == null) {throw new RuntimeException("Unknown initial tag: " + parser.getName());}return drawable;}
从这段代码中我们可以发现,最主要的工作是由方法createFromXmlInner来完成的,我们进去看看:
/*** Create from inside an XML document. Called on a parser positioned at* a tag in an XML document, tries to create a Drawable from that tag.* Returns null if the tag is not a valid drawable.*/public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)throws XmlPullParserException, IOException {Drawable drawable;final String name = parser.getName();if (name.equals("selector")) {drawable = new StateListDrawable();} else if (name.equals("level-list")) {drawable = new LevelListDrawable();} else if (name.equals("layer-list")) {drawable = new LayerDrawable();} else if (name.equals("transition")) {drawable = new TransitionDrawable();} else if (name.equals("color")) {drawable = new ColorDrawable();} else if (name.equals("shape")) {drawable = new GradientDrawable();} else if (name.equals("scale")) {drawable = new ScaleDrawable();} else if (name.equals("clip")) {drawable = new ClipDrawable();} else if (name.equals("rotate")) {drawable = new RotateDrawable();} else if (name.equals("animated-rotate")) {drawable = new AnimatedRotateDrawable(); } else if (name.equals("animation-list")) {drawable = new AnimationDrawable();} else if (name.equals("inset")) {drawable = new InsetDrawable();} else if (name.equals("bitmap")) {drawable = new BitmapDrawable();if (r != null) {((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());}} else if (name.equals("nine-patch")) {drawable = new NinePatchDrawable();if (r != null) {((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());}} else {throw new XmlPullParserException(parser.getPositionDescription() +": invalid drawable tag " + name);}drawable.inflate(r, parser, attrs);return drawable;}
噢噢,原来是这样啊,我定义什么样类型的图片,最后就有什么样的Java类型与之对应,原来我的selector对应StateListDrawable,恍然大悟,接下来就容易处理了。