Android根据资源名获取资源Id

如果是只需要代码的话,看 解决方法 位置!

一般情况下我们都是直接使用资源 Id 来获取资源的,简单而又方便.

例如:

imageView.setImageResource(R.drawable.ic_launcher_background)

但是有些情况下,这种方式就显的有点复杂了.

例如这么一种情况 :

要根据 type 的值来选择对应的图片.

type : 取值范围是0…9

对应的图片为: iconvip0, iconvip1 …. iconvip9.

这时候如果用资源 id 的方式来取图片的话,代码是这样的:

switch (type){
        case 0:
            imageView.setImageResource(R.drawable.iconvip0);
            break;
        case 1:
            imageView.setImageResource(R.drawable.iconvip1);
            break;
        case 2:
            imageView.setImageResource(R.drawable.iconvip2);
            break;
        case 3:
            imageView.setImageResource(R.drawable.iconvip3);
            break;
        case 4:
            imageView.setImageResource(R.drawable.iconvip4);
            break;
        case 5:
            imageView.setImageResource(R.drawable.iconvip5);
            break;
        case 6:
            imageView.setImageResource(R.drawable.iconvip6);
            break;
        case 7:
            imageView.setImageResource(R.drawable.iconvip7);
            break;
        case 8:
            imageView.setImageResource(R.drawable.iconvip8);
            break;
        case 9:
            imageView.setImageResource(R.drawable.iconvip9);
            break;
    }

看到这样的代码,虽然代码很简单,也是有点头大的.何况这才10个,若是100个呢,1000个呢不敢想象…


解决方法

一行代码直接搞定:

imageView.setImageResource(getResources().getIdentifier("iconvip"+type,"drawable",getPackageName()));

其实就是 Resources 的一个方法 getIdentifier(String name, String defType, String defPackage)

第一个参数 name : 就是资源名

第二个参数 defType : 就是资源所存在的文件夹

第三个参数 defPackage : 就是程序的包名

还有另一种写法:

imageView.setImageResource(getResources().getIdentifier(packageName + ":drawable/iconvip"+type, null, null);

同样的我们还可以利用它来获取一些尺寸信息,如状态栏的高度

int resourceId = this.getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        int statusBarHeight = this.getResources().getDimensionPixelSize(resourceId);
    }
源码部分

好奇的话,我们跟踪源码看看.

// Resources 类
public int getIdentifier(String name, String defType, String defPackage) {
    return mResourcesImpl.getIdentifier(name, defType, defPackage);
}

又调用了 ResourcesImpl类,跟进去看看吧.

// ResourcesImpl类
int getIdentifier(String name, String defType, String defPackage) {
    if (name == null) {
        throw new NullPointerException("name is null");
    }
    try {
        return Integer.parseInt(name);
    } catch (Exception e) {
        // Ignore
    }
    return mAssets.getResourceIdentifier(name, defType, defPackage);
}

可以看到最后其实是调用了mAssetsgetResourceIdentifier方法

mAssets其实是AssetManager

我们再看看AssetManager里面

native final int getResourceIdentifier(String name,
                                                   String defType,
                                                   String defPackage);

到这里看到实际上是一个 native 方法.

总结

getIdentifier 这个方法在某些的特定的情况下能给我们提供便利,但是还是尽量的少使用它,因为在有资源 id 的时候,使用资源 id来获取资源,效率会更高.