56

序言:这个问题已经过时了,它是在首选的Android开发环境是带有Android插件的Eclipse时编写的。


我有一个Java Android项目有一段时间了。今天,我已经将Android开发工具更新到了谷歌的最新版本。项目失败了,我收到了一堆“case表达式必须是常量表达式”的编译错误消息。

结果是,现在生成的R.java文件有所不同。以前,它会有一堆

公共静态最终int MyID=0x12340000;

声明;现在,它看起来(在清理/重建之后)如下:

公共静态int MyID=0x12340000;

最终的不见了。所以我在资源ID上的所有开关(我有一些)都是错误的。请问发生了什么事?只有我吗?这里的理由是什么?在任何地方都有记录吗?我能带吗最终的不知怎么回来了?

7个答案7

重置为默认值
43

这大约发生在昨天,当SDK/ADT14发布时:

自ADT 14起,库项目中的资源常量不再是最终。这在中有更详细的解释http://tools.android.com/tips/nonstant-fields

ADT 14提供了一个快速修复程序:http://tools.android.com/recent/switchstatementconversion

引用基本原理:

组合多个库项目时字段(必须是唯一的)可能会发生冲突。ADT 14之前,所有字段是最终的,因此,所有的图书馆都必须拥有资源和相关的Java代码与主代码一起重新编译在使用它们时进行投影。这对性能不利,因为它使得构建速度非常慢。它还阻止了分发库不包含源代码的项目,限制了使用范围图书馆项目。

字段不再是最终字段的原因是,这意味着库jar可以编译一次,然后直接在其他项目中重用。除了允许发布库项目的二进制版本(r15中提供)外,这还使得构建速度更快。

7
  • 2
    实际上,这很有道理。我知道他们从哪里来。Android库只是链接的源代码,而不是编译的库,这对我来说是一个小小的痛点。此外,谷歌还提供了一个神奇的重构器。 评论 2011年10月20日19:27
  • 11
    这只是Android团队愚蠢的设计决策的结果。每当你看到一些生成的文件中有一堆神奇的数字常量时,你应该看看它。谢谢你,谷歌因为完全缺乏远见而破坏了你开发人员的一堆源代码。公共静态整数。好多了?!
    – 内特
    评论 2011年11月12日1:15
  • 4
    这个答案被标记为解决方案,但我看不到…非常好的讨论、建议、文档链接等等。。。什么是具体的解决方案?为了解决这个问题,我应该在代码中更改什么?还是没有解决方案然后请用一个词回答:“不”?
    – 维塔利
    评论 2020年12月25日5:56
  • 1
    @俄罗斯无人机飞行你读过任何链接吗?他们说,如果需要有条件地处理资源ID,可以使用if-else子句而不是switch语句。Switch语句将要求ID是最终的,这已经有九年多没有了。 评论 2020年12月26日11:40
  • 2
    这将使您做很多额外的工作,并对代码进行许多不必要的修改,只需添加android.nonFinalResIds=假在gradle.properties文件中可以工作。
    – 应用
    评论 2023年7月29日0:33
14

您可以切换到使用If/Else语句,警告就会消失。

样品:

@覆盖单击时公共无效(最终视图v){//查找按下的按钮最终int按钮View=v.getId();当前字符串=fromEditText.getText().toString();if(buttonView==R.id.bA){当前+=getString(R.string.a);} }
1
  • 9
    😂😭🤣😀❤️ 不错!
    – 一个
    评论 2020年11月11日18:12
13

只需添加括号:

开关(view.getId()){案例(R.id.view1):断裂;案例(R.id.view2):断裂;}
4
  • 5
    为什么这样做有效?这样做安全吗? 评论 2022年12月5日22:49
  • @SMBiggs我认为它使它成为某种常量,而不仅仅是一个引用。我在许多客户的生产模式中使用了几个月,但我没有收到任何崩溃或投诉。 评论 2022年12月6日9:54
  • case语句在编译时进行硬编码。你需要的是保持环境恒定的资源,而不是。带或不带括号。。这类似于:“final int VIEW_ID_1=R.ID.view1;”如果稍后更改资源,则开关将失败,因为它将不再与硬编码资源匹配。
    – 克里斯
    评论 2023年2月20日8:33
  • 2
    这样做的唯一原因是可能会使探测器错过这种情况。但是解决id实际上是非final的情况(Java编译器将不会编译此代码)。因此,它充其量只是一个乐队助手(它所做的一切都使警告沉默,但它并没有解决问题)。 评论 2023年4月28日10:32
6

谷歌建议您使用if/else条件

http://tools.android.com/tips/nonstant-fields

要自动更改它们,可以将插入符号放在转换关键字和按键中高音+输入在Windows上(选项+输入在Mac上)并选择将“switch”替换为“if”

5

这是因为在新的AGP版本中,谷歌将所有搜索ID设为非最终版本,添加android.nonFinalResIds=假在您的梯度.属性文件,以确保AGP生成最终res-ids将使您避免修改代码。

2
  • @塞瓦·阿列克塞耶夫,我可以确认,在8.0版中,它也刚刚再次发生 评论 2023年10月20日4:38
  • 奇怪的是,我在2017年编写了一个完整的android应用程序(谢天谢地,这是我唯一必须编写的应用程序),自动生成的代码和“推荐”的代码都使用了switch语句。(当然,我的目标是一个较旧的Android操作系统版本……不过,情况非常糟糕)。这让我怀疑Java的智慧开关()全部声明。如果硬件没有出现故障,我也不必“重新编译”以“重新定位”一部较新的手机,并最终实际重新编写整个应用程序,那么这一切都不重要。 评论 2023年11月15日20:35
1

你应该使用视图绑定!

机器人{...查看绑定{enabled=真}}
2
  • 1
    不适用于菜单。最初的问题主要是关于菜单ID。 评论 2021年5月19日20:33
  • 1
    添加了很多类,但实际上并没有解决问题,它只是使用另一种方法来识别和处理视图。 评论 2021年8月18日19:24
-1

只需在模块级别中添加此剪辑建筑梯度文件:

机器人{...lint选项{禁用“NonConstantResourceId”}}

更多信息:https://developer.android.com/studio/write/lint#gradle

2
  • 禁用lint选项的任何缺点。 评论 2021年1月28日9:32
  • 18
    小心,这只是禁用了Lint警告,实际上它本身并没有解决问题。 评论 2021年1月30日16:06

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.