【发布时间】:2013-06-27 15:16:36
【问题描述】:
应用程序抛出异常
android.content.res.Resources$NotFoundException: 字符串资源 ID
我的情况并不常见(因为给定的 ID 确实存在)。我问这个问题是为了自己回答。
请看下面我的回答为什么会发生这种情况以及为什么会发生在我身上。
【问题讨论】:
标签: android string exception resources locale
应用程序抛出异常
android.content.res.Resources$NotFoundException: 字符串资源 ID
我的情况并不常见(因为给定的 ID 确实存在)。我问这个问题是为了自己回答。
请看下面我的回答为什么会发生这种情况以及为什么会发生在我身上。
【问题讨论】:
标签: android string exception resources locale
您可能已经发现,当您尝试将某个整数设置为字符串时会发生此错误,例如:
代码中的某处 some_variable 被声明为 int 并且您想显示其值,因此您尝试使用 setText() 方法将其设置为 some_textview:
int some_variable = 0;
TextView txtView = (TextView) findViewById(R.id.someTextView);
... some code/calculations etc...
txtView.setText(some_variable); // exception! some_variable is an int value
也可以是任何返回 int 的方法返回的结果,例如:
txtView.setText(someString.length());// exception! String.length() returns an int value
txtView.setText(someSet.size());// exception! Set.size() returns an int value
等等
这些导致Resources$NotFoundException 因为没有String 资源具有这样的编号(id)。
您很可能知道在每次构建时都会在构建文件夹中创建一个R.java 文件。该文件包含静态变量,其中在 string.xml String 中声明的每个变量都有自己唯一的 id 和一些 int 值,并且您在代码中使用的这个 id 作为 R.string。 id。这就是异常的原因 - 系统会尝试找到与给定值对应的 R.string.id 字符串,但在大多数情况下显然会失败。这也是 setText() 接受整数值并且 IDE 不警告您的原因。
在某些情况下,您的some_variable 可能会有一个与某个id 相对应的值。这些都是棘手的情况,因为不会抛出异常,并且您会看到一些意想不到的文本(实际上对应于 R.string.id)而不是变量值。
这个问题的解决方法很简单(如果必须显示some_variable的值):
txtView.setText(String.valueOf(some_variable));
还有许多人试图以与Toast 消息相同的方式设置int 值,例如:
int some_variable = 0;
... some code/calculations etc...
Toast.makeText(this, some_variable, Toast.LENGTH_LONG).show();
Toast.makeText(getBaseContext(), someSet.size(), Toast.LENGTH_LONG).show();
修复方法是一样的:
int some_variable = 0;
... some code/calculations etc...
Toast.makeText(this, String.valueOf(some_variable), Toast.LENGTH_LONG).show();
Toast.makeText(getBaseContext(), String.valueOf(some_Set.size()), Toast.LENGTH_LONG).show();
您可能遇到了使用Integer(some_variable).toString() 方法的方法。不算太差。然而,这意味着将应用 1 个额外的操作(将 int 值包装为 Integer),并且只能使用整数值(或将抛出 NumberFormatException),而对于 String.valueOf(some_variable),值类型无关紧要,它适用于任何类型值,包括所有原语(float、double、byte、long 等),并且永远不会抛出任何异常。
还有一些其他情况 - rare cases are described here 重点是在 IDE 中清理项目。
如果您非常确定您没有以上述方式传递任何整数,而且这发生在已发布的应用程序中并且在开发时没有发生,则可能是 Locale 案例。如果您的应用具有 Locale 取决于 String 资源,并且当您测试它时,您可能使用您所在地区特定的 Locale 设备进行了测试,因此没有检测到问题。但是(请记住!)在这种情况下,您必须提供位于项目的res\values 文件夹中的默认strings.xml,如果您错过了它,就是这种情况。假设某个来自德国的用户(其设备默认 Locale 是 DE)尝试运行这样的应用程序,该应用程序在文件夹 values-en 和 values-it 中只有 strings.xml (但在 @ 中没有 strings.xml 987654353@ 也不在 values-de 文件夹中)。在这种情况下,应用程序将首先尝试定位 values-de\strings.xml 但失败,然后它将尝试使用默认的 values\strings.xml 并再次失败,因此它将崩溃抛出 Resources$NotFoundException。
就像我之前提到的,解决这个问题的方法是在项目的res\values 文件夹中提供默认的strings.xml,因此对于任何不受支持的语言环境,都将使用默认的语言环境(通常是英语)。另一种方法是在运行时为您的应用程序设置适当的默认语言环境(例如在 Application 扩展类中),如果它在具有不受支持的语言环境的设备上运行,例如(假设您想默认使用 en 语言环境):
Locale locale = getAppLocale(context);
String localeLang = locale.getLanguage();
// default locale is EN but available are EN and RU
if (!localeLang.equalsIgnoreCase("en") && !localeLang.equalsIgnoreCase("ru")) {
locale = new Locale("en");
Configuration config = new Configuration();
config.locale = locale;
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}
【讨论】:
只需使用 String.valueOf(your_value_here) 当您尝试在 textview 中设置 int 数据类型但尝试 String.valueOf() 函数时,通常会发生此错误。
【讨论】: