Android getIdentifier用法

前言

最近这段时间在忙着开发一个Android游戏,当然并不是真正的游戏,只是一个伪游戏而已,因为应用需要的图片资源和布局都比较多,所以难免就出现了下面这种类型的代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
switch (index) {
case 1:
mView = mInflater.inflate(R.layout.layout_gift_one, null);
break;
case 2:
mView = mInflater.inflate(R.layout.layout_gift_two, null);
break;
case 3:
mView = mInflater.inflate(R.layout.layout_gift_three, null);
break;
case 4:
mView = mInflater.inflate(R.layout.layout_gift_four, null);
break;
case 5:
mView = mInflater.inflate(R.layout.layout_gift_five, null);
break;
case 6:
mView = mInflater.inflate(R.layout.layout_gift_six, null);
break;
}

对于我这种有代码洁癖的人,每次看到这种代码我心里着实是不舒服的,今天上午写代码的时候,遇到一个这样的需求,简化一下大致是这样的:

需求

有6个textview用于显示6种商品的数量,然后定义了一个长度为6的数组用于存放6种商品的数量,那么有一个需求是要在特定的条件下将6种商品的数量置为0,同时在textview显示

分析

遇到这种问题,数组置0很简单,但是问题来了:6个textview都是从布局文件中获取的,每个textview的资源id不一样,每个textview的名字都不一样,相当于要执行6次findviewByIdxxxTextView.setText("0"),我一想到这里,感觉如果这样写简直太丑陋了

心想既然标识商品的数量用的就是一个数组,那么可以不可以把6个textview也放到数组里面?正好这两天在stackoverflow上看另一个问题的时候,好像看到过类似的用法,模糊中记得好像是用的getIdentifier,于是就搜索了一下,果然可以,成功的将6个textview用一行代码就放到了一个长度为6的数组中,不用6次findViewById,也不用6次xxTextView.setText(“0”)了,一个循环就搞定了

实现

学习要举一反三,学以致用,那么当我再次看到项目中开头那段代码的时候,心里想这个不是也可以使用getIdentifier简化吗,于是简化之后上面的代码就变成这样了。

1
2
3
int layoutId = getResources().getIdentifier(
"layout_gift_" + index, "layout", getPackageName());
mView = mLayoutInflater.inflate(layoutId, null);

是不是看起来整洁了很多

扩展

然后又点进去getIdentifier方法的源码里面看了一下,用法简介是这样写的:

1
2
3
4
5
6
7
/**
* Return a resource identifier for the given resource name. A fully
* qualified resource name is of the form "package:type/entry". The
* first two components (package and type) are optional if defType and
* defPackage, respectively, are specified here.
**/
public int getIdentifier(String name, String defType, String defPackage)

也就是说传递参数的方式有两种情况:

  1. 第一个参数按照package:type/entry的方式传递的话,那么后面两个type和package参数是可选的,也就是可以传null,就像这样:

    1
    2
    int layoutId = getResources().getIdentifier(
    "com.huhulab.xxx:layout/layout_1",null,null);

    第一个参数的格式也就是:包名+”:”+资源属性类型+”/“+资源名,其中资源属性类型就是指你要获取的资源是layout,id或者drawable之类的

  2. 就是按照我上面的那种方法传递,像这样:

    1
    2
    int textId = getResources().getIdentifier(
    "text1",id,"com.huhulab.xxx");

    三个参数分别是:资源名,资源属性类型,包名

注意

源码简介里面还有这么一句提示:

1
2
Note: use of this function is discouraged.  It is much more
efficient to retrieve resources by identifier than by name.

也就是说并不鼓励使用这个方法,因为通过id获取资源比通过名字获取资源更高效,也就是说这种方法耗时可能会比较久,所以除非必须不要过多使用这个方法
当然因为R.layout和R.id等其实都是一个内部类,你也可以通过反射获取类中的某一个变量,也就是你要找的那个资源名