Android module switch语句报错问题

Posted createchance

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android module switch语句报错问题相关的知识,希望对你有一定的参考价值。

在实际的项目中,大家经常将我们的项目差分成多个module以方便项目的并行开发。在moudle中,有一个问题很多人都遇见过,如下:

这种问题咋一看有点不理解,为什么我们的id不能在case中使用了呢?为了弄明白这个问题,我们先看下tv_title这个变量的定义,也就是R文件中的定义:

我们看到,这里的tv_title变量不是一个final的,但是我们switch中case条件必须是常量或者final的,也就是说case条件必须是一个不能在编译之后变化的值。这就能解释为什么会遇到上面的问题了。
但是,我们显然不能就这么满足了,技术想要精湛,必须要打破砂锅问到底,这里就有两个问题必须要解决:
1. 为什么module中的id不是final的?
2. 为什么switch的case条件必须是常量或者final的?
我们一个一个地探索这些问题。

为什么module中的id不是final的?

其实我们展开刚才studio提示的错误,就能看到:

这里给出了一部分回答,简单来说就是自从sdk tools r14之后,module中的所有的id都不是final的,也就是说只要我们使用的编译工具是>14的,都会出现这个问题。但是这里并没有给出为什么14之后moudle中的id不是final的答案。为了弄明白这个问题,我们需要知道android的资源编译问题。
在android中国中所有的资源都是编号使用的,而不是直接使用的,这样有利于将资源和代码解耦,并且方便灵活管理。这样处理有一个重要的前提,那就是需要保证在整个项目中是唯一的,并且一旦确定就不能在改变,不然就会出现资源冲突。于是,早期的做法就是所有的资源id都是final的这样在代码静态角度就固定死了这个id不能变化。但是这样有一个问题,那就是如果我们的工程比较庞大,有若干个module,每次一个module编译的时候,其他的module的编译的都要重新进行一次,这样才能保证资源id唯一性。这样显然会减慢构建的速度,并且发布module提供给别人使用的时候也是很不方便的,因为你的id都是final的,而我们给出去的又是一个aar文件,这样的话别人是没有办法使用的。后来也就是14之后,google将module中的资源id定义为非final的,这样的话,每个module就可以独立进行编译了,可以只编译发生变化的module,这样可以加快构建的速度,并且没有发布的限制。
对于这个问题,google有一个说明文档,大家可以看看:
https://sites.google.com/a/android.com/tools/tips/non-constant-fields

为什么switch的case条件必须是常量或者final的?

这个问题涉及java switch语句的编译问题。关于这个问题大家可以看看这个文章:
https://book.2cto.com/201507/53004.html
这个文章说明switch语句会根据case条件值的离散程度分别使用switchtable或者lookupswitch指令执行swtch语句。但是不论是那种执行指令,都是使用一个确定的常量作为查询表index的,这些值都是在编译的时候就确定的。这样做的目的是可以在运行的时候加快查询的速度,比如我们在lookupswitch中可以使用二分查找方法快速找到我们的index,而不用执行慢速的线性扫描法。因此我们switch语句中的case条件值必须是在编译的时候就能确定的。

这个问题的解决办法?

其实studio已经给出的解决办法:

就是转换成if条件语句!!

以上是关于Android module switch语句报错问题的主要内容,如果未能解决你的问题,请参考以下文章

在AS上导入第三方module项目后报错提示:Resource IDs cannot be used in a switch statement in Android library modules

在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案

Android检查int是不是在区间+ switch语句中

关于switch中case的用法!

Android:对超过 1 个按钮使用带有 setOnClickListener/onClick 的 SWITCH 语句?

在switch语句中将Android中的字符串从硬编码更改为字符串资源