Android 资源 ID 突然不是最终的,switch() 损坏了

发布于 2024-12-10 19:04:04 字数 520 浏览 1 评论 0原文

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


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

事实证明,R.java 文件现在以不同的方式生成。以前,它会有一堆

public static final int MyID=0x12340000;

语句; 现在,它会有一堆语句。现在,它看起来(在清理/重建之后)像这样:

public static int MyID=0x12340000;

final 消失了。因此,我拥有的(我有一些)资源 ID 上的所有开关都是错误的。请问发生什么事了?只有我吗?这里的理由是什么?它在任何地方都有记录吗?我可以以某种方式恢复final吗?

PREAMBLE: this question is quite obsolete, it was written when the preferred Android dev environment was Eclipse with the Android plugin.


I had a Java Android project for a while. Today, I've updated the Android dev tools to the Google's latest. And the project broke - I get a bunch of "case expressions must be constant expressions" compilation error messages.

Turns out that the R.java file is being now generated differently. Formerly, it would have a bunch of

public static final int MyID=0x12340000;

statements; now, it looks (after a clean/rebuild) like this:

public static int MyID=0x12340000;

final is gone. So all switches on resource IDs that I had (and I had a few) are wrong. What happened, please? Is it just me? What's the rationale here? Is it documented anywhere? Can I bring final back somehow?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

撩发小公举 2024-12-17 19:04:04

这发生在昨天,当 SDK/ADT 14 发布时:

从 ADT 14 开始,库项目中的资源常量不再
最终的。 http://tools.android.com/tips/non-constant-fields


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

引用自这理由:

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

这些字段不再是 Final 的原因是,这意味着库 jar 可以编译一次并直接在其他项目中重用。除了允许分发库项目的二进制版本(在 r15 中出现)之外,这还可以加快构建速度。

This happened about yesterday, when the SDK/ADT 14 got released:

As of ADT 14, resource constants in library projects are no longer
final. This is explained in greater detail in http://tools.android.com/tips/non-constant-fields

There's a quickfix available from ADT 14: http://tools.android.com/recent/switchstatementconversion

To quote from the rationale:

When multiple library projects are combined, the actual values of the
fields (which must be unique) could collide. Before ADT 14, all fields
were final, so as a result, all libraries had to have all their
resources and associated Java code recompiled along with the main
project whenever they were used. This was bad for performance, since
it made builds very slow. It also prevented distributing library
projects that didn't include the source code, limiting the usage scope
of library projects.

The reason the fields are no longer final is that it means that the library jars can be compiled once and reused directly in other projects. As well as allowing distributing binary version of library projects (coming in r15), this makes for much faster builds.

扛刀软妹 2024-12-17 19:04:04

只需添加括号即可:

switch (view.getId()) {
    case (R.id.view1):
        break;
    case (R.id.view2):
        break;
}

Just add parentheses:

switch (view.getId()) {
    case (R.id.view1):
        break;
    case (R.id.view2):
        break;
}
仅此而已 2024-12-17 19:04:04

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

样本:

    @Override
    public void onClick(final View v) {
        //finds which button was pressed
        final int buttonView = v.getId();
        String current = fromEditText.getText().toString();
        if (buttonView == R.id.bA) {
            current += getString(R.string.a);
        } 
  }

You could switch over to using If/Else statements and the warning will go away.

Sample:

    @Override
    public void onClick(final View v) {
        //finds which button was pressed
        final int buttonView = v.getId();
        String current = fromEditText.getText().toString();
        if (buttonView == R.id.bA) {
            current += getString(R.string.a);
        } 
  }
倥絔 2024-12-17 19:04:04

Google 建议您使用 if/else 条件

http://tools. android.com/tips/non-constant-fields

要自动更改它们,您可以将脱字符号放在 switch 关键字上,然后按 Alt +在 Windows 上按 Enter(在 Mac 上按 Option + Enter),然后选择将“switch”替换为“if”

Google recommends you use if/else conditions

http://tools.android.com/tips/non-constant-fields

To change them automatically you can place the caret on the switch keyword and press Alt + Enter on Windows (Option + Enter on Mac) and select Replace 'switch' with 'if'

梦罢 2024-12-17 19:04:04

这是因为在新的 AGP 版本中,Google 将所有资源 ID 设为非最终 ID,请在项目根目录下的 gradle.properties 文件中添加 android.nonFinalResIds=false 来确保 AGP 生成最终的 res id 将使您避免修改代码。

This is because in new AGP verion, Google make all rescours ids non final, add android.nonFinalResIds=false in your gradle.properties file in the root directory of your project to make sure the AGP generate final res ids will make you avoid modify your code.

始终不够爱げ你 2024-12-17 19:04:04

您应该使用视图绑定

android {
    ...
    viewBinding {
        enabled = true
    }
}

You should use view binding!

android {
    ...
    viewBinding {
        enabled = true
    }
}
你另情深 2024-12-17 19:04:04

删除“final”关键字意味着 ID 不再是常量,因此不能用作需要常量值的 switch 语句中的标签。

Switch 语句的基础知识

在 Java 中,switch 语句要求 case 标签是常量表达式。这意味着 case 标签中使用的值必须在编译时已知并固定。您不能使用可以在运行时更改的变量。

switch (value) {
    case CONSTANT1:
        // Do something
        break;
    default:
        // Default action
}

错误代码示例:

public class Example {
    public static int myVariable = 10;

    public static void main(String[] args) {
        int value = 10;

        switch (value) {
            case myVariable:  // Compile-time error
                System.out.println("Value is myVariable");
                break;
            default:
                System.out.println("Value is not myVariable");
                break;
        }
    }
}

**

错误:case 表达式必须是常量表达式

**

正确的代码示例:

public class Example {
    public static final int MY_CONSTANT = 10;

    public static void main(String[] args) {
        int value = 10;

        switch (value) {
            case MY_CONSTANT:
                System.out.println("Value is MY_CONSTANT");
                break;
            default:
                System.out.println("Value is not MY_CONSTANT");
                break;
        }
    }
}

Android 和 R.java 更改

之前的行为:

public static final int main = 0x7f030004;

更新的行为:< /强>
从 ADT 14 开始,Android 库项目现在使用:

public static int main = 0x7f030004;

final 关键字已从资源 ID 中删除,使其变得非常量。

解决方案
switch 语句转换为 if-else 语句来处理这些情况:

public void onClick(View view) {
    int id = view.getId();
    if (id == R.id.btnBlack) {
        // Handle btnBlack click
    } else if (id == R.id.btnGreen) {
        // Handle btnGreen click
    } 
}

The removal of the 'final' keyword means that IDs are no longer constants, and therefore cannot be used as labels in a switch statement, which requires constant values.

Basics of Switch Statements

In Java, a switch statement requires case labels to be constant expressions. This means that the values used in the case labels must be known and fixed at compile time. You cannot use variables that can change at runtime.

switch (value) {
    case CONSTANT1:
        // Do something
        break;
    default:
        // Default action
}

Wrong Code Example:

public class Example {
    public static int myVariable = 10;

    public static void main(String[] args) {
        int value = 10;

        switch (value) {
            case myVariable:  // Compile-time error
                System.out.println("Value is myVariable");
                break;
            default:
                System.out.println("Value is not myVariable");
                break;
        }
    }
}

**

Error: case expressions must be constant expressions.

**

Correct Code Example:

public class Example {
    public static final int MY_CONSTANT = 10;

    public static void main(String[] args) {
        int value = 10;

        switch (value) {
            case MY_CONSTANT:
                System.out.println("Value is MY_CONSTANT");
                break;
            default:
                System.out.println("Value is not MY_CONSTANT");
                break;
        }
    }
}

Android and R.java Changes

Previous Behavior:

public static final int main = 0x7f030004;

Updated Behavior:
As of ADT 14, Android library projects now use:

public static int main = 0x7f030004;

The final keyword has been removed from resource IDs, making them non-constant.

Solution
Convert switch statements to if-else statements to handle these cases:

public void onClick(View view) {
    int id = view.getId();
    if (id == R.id.btnBlack) {
        // Handle btnBlack click
    } else if (id == R.id.btnGreen) {
        // Handle btnGreen click
    } 
}
小情绪 2024-12-17 19:04:04

只需将这段代码添加到您的模块级 build.gradle 文件中即可:

android {
    ...
    lintOptions {
        disable 'NonConstantResourceId'
    }
}

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

Just add this snipped in your module-level build.gradle file:

android {
    ...
    lintOptions {
        disable 'NonConstantResourceId'
    }
}

More:
https://developer.android.com/studio/write/lint#gradle

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文