19

应用程序抛出异常

android.content.res.Resources$NotFoundException:字符串资源 ID

我的情况并不常见(因为给定的 ID 确实存在)。我问这个问题是为了自己回答。

请看下面我的回答为什么会发生这种情况以及为什么会发生在我身上。

4

2 回答 2

48

您可能已经发现,当您尝试将某个整数设置为字符串时会发生此错误,例如:代码中的某处some_variable被声明为int并且您希望显示其值,因此您尝试将其设置为some_textviewusingsetText()方法:

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。身份证。这是异常的原因 - 系统将尝试查找 R.string。id字符串对应于给定值,但在大多数情况下显然失败。这也是 setText() 接受整数值并且 IDE 不警告您的原因。在某些情况下,您some_variable可能会碰巧有一个对应于某个id的值. 这些都是棘手的情况,因为不会抛出异常,并且您会看到一些意外的文本(实际上对应于 R.string.id 而不是变量值。
这个问题的解决方案很简单(如果some_variable必须显示 的值):

txtView.setText(String.valueOf(some_variable));

还有许多人试图以int与消息相同的方式设置值,Toast例如:

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 等)并且永远不会抛出任何异常。
还有一些其他情况 -这里描述了罕见的情况,重点是在 IDE 中清理项目。
如果您非常确定您没有以上述方式传递任何整数,而且这种情况发生在已发布的应用程序中,并且在开发时没有发生这种情况可能是一种Locale情况。如果您的应用Locale依赖String资源,当您测试它时,您可能使用您所在地区Locale的特定设备进行了测试,因此没有检测到问题。但是(请记住!)在这种情况下,您必须提供strings.xml位于res\values项目文件夹中的默认值,如果您错过了它,就是这种情况。假设某个来自德国的用户(其设备默认Locale为 DE)尝试运行此类应用程序,该应用程序仅strings.xml在文件夹中values-envalues-it(但在文件夹中和文件夹strings.xml中都values没有values-de)。在这种情况下,应用程序将首先尝试定位values-de\strings.xml但失败,然后它将尝试使用默认值values\strings.xml并再次失败,因此它将崩溃抛出Resources$NotFoundException。就像我之前提到的,这个问题的修复是
提供一个默认值strings.xmlres\values项目的文件夹,因此对于任何不受支持的语言环境,将使用默认的语言环境(通常是英语)。另一种方法是在运行时为您的应用程序设置适当的默认语言环境(例如在 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());
    }
于 2013-06-30T08:32:21.370 回答
0

只需使用 String.valueOf(your_value_here) 当您尝试在 textview 中设置 int 数据类型但尝试 String.valueOf() 函数时,通常会发生此错误。

于 2020-12-13T15:00:58.303 回答