Resource()中的getDrawable(int id)是怎样将图片显示出来的

首先看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;
    }

 
 
 
 
 
 
 
 

                
在Android应用,如果你需要在界面展示的文字内容支持多种语言,并且相应的图片资源也要随着语言切换而变化,你可以通过以下步骤切换drawable目录下的图片: 1. 创建多套drawable资源文件夹:在res目录下创建`drawable-en`, `drawable-zh-rCN`等文件夹,分别对应英语和其他语言。例如,对于文,你可以创建`drawable-zh-rCN`。 2. 按照语言国际化规则提供图片资源:为每种语言准备一张图片并放在对应的文件夹里。比如,对于文版的“设置”图标,你可以在`drawable-zh-rCN`里放一个名为`ic_setting.zh.png`的图片,而在`drawable-en`里放`ic_setting.en.png`。 3. 使用Resources API动态加载图片:在你的代码,可以获取当前的语言环境,然后从相应的drawable文件夹加载图片。例如,你可以使用`getResources().getDrawable(R.drawable.ic_setting)`,这里`R.drawable.ic_setting`会被替换为你实际存放该图片的资源ID。 4. 判断语言环境:使用`Configuration`类的`locale`属性来获取用户设备的语言偏好,然后根据`Locale`对象选择对应的图片。 ```java Resources res = getResources(); String language = Locale.getDefault().getLanguage(); // 获取语言 int resourceId; if (language.equals("zh")) { resourceId = R.drawable.ic_setting_zh; } else if (language.equals("en")) { resourceId = R.drawable.ic_setting_en; } else { resourceId = R.drawable.ic_setting_default; // 默认情况或其他通用图片 } Drawable drawable = res.getDrawable(resourceId); // 使用drawable对象显示图片 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值