Skip to content

Latest commit

 

History

History
71 lines (55 loc) · 3.3 KB

Library项目中资源id使用case时报错.md

File metadata and controls

71 lines (55 loc) · 3.3 KB

Library项目中资源id使用case时报错

在平时开发的过程中对一些常量的判断,都是使用switch case语句,因为switch caseif else的效率稍高。
但是也遇到了问题,就是在library中使用时会报错:

public void testClick(View view) {
    int id = view.getId();
    switch (id) {
        case R.id.bt_pull:

            break;
        case R.id.bt_push:

            break;
    }
}

我们来看一下错误提示:

Image

意思就是在Android LibraryModule中的switch语句不能使用资源ID.这是为什么呢? 我们都知道R文件中都是常量啊,public static final的,为什么不能用在switch语句中,继续看下去:

Resource IDs are non final in th library projects since SDK tools r14, means that the library code cannot treat this IDs as constants.

说的灰常明白了,也就是说从14开始,library中的资源id就不是final类型的了,所以不是常量了。

在一个常规的Android项目中,资源R文件中的常量都是如下这样声明的:
public static final int main=0x7f030004; 然后,从ADT14开始,在library项目中,它们将被这样声明:
public static int main=0x7f030004;

也就是说在library项目中这些常量不是final的了。为什么这样做的原因也非常简单:当多个library项目结合时,这些字段的实际值(必须唯一的值)可能会冲突。在ADT14之前,所有的字段都是final的,这样就导致了一个结果,就是所有的libraries不论何时在被使用时都必须把他们所有的资源和相关的Java代码都伴随着主项目一起重新编译。这样做是不合理的,因为它会导致编译非常慢。这也会阻碍一些没有源码的libraray项目进行发布,极大的限制了library项目的使用范围。

那些字段不再是final的原因就是意味着library jars可以被编译一次,然后在其他项目中直接被服用。也就是意味着允许发布二进制版本的library项目(r15中开始支持),这让编译变的更快。

然而,这对library的源码会有一个影响。类似下面这样的代码就将无法编译:

public void testClick(View view) {
    int id = view.getId();
    switch (id) {
        case R.id.bt_pull:

            break;
        case R.id.bt_push:

            break;
    }
}

这是因为swtich语句要求所有case后的字段,例如R.di.bt_pull在编译的时候都应该是常量(就像可以直接把值拷贝进.class文件中)

当然针对这个问题的解决方法也很简单:就是把switch语句改成if-else语句。幸运的是,在eclise中这是非常简单的。只需要在switch的关键字上按Ctrl+1Mac上是Cmd+1)。(eclipse都辣么方便了,Studio更不用说了啊,直接按修复的快捷键就阔以了)。
上面的代码就将变成如下:

public void testClick(View view) {
    int id = view.getId();
    if (id == R.id.bt_pull) {
    } else if (id == R.id.bt_push) {
    }
}

这在UI代码和性能的影响通常是微不足道的 - -!。