19

アプリケーションが例外をスローする

android.content.res.Resources$NotFoundException: 文字列リソース ID

私のケースはそれほど一般的ではありませんでした (特定の ID が存在するため)。私は自分で答えるためにこの質問をしました。

なぜこれが起こるのか、なぜそれが私に起こったのか、私の答えの下を見てください。

4

2 に答える 2

48

some_variableコードのどこかで次のように整数を文字列として設定しようとすると、このエラーが発生することが既にわかっているかもしれませintん。some_textviewsetText()

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

これらは、そのような番号 (id) を持つリソースResources$NotFoundExceptionがないため、原因となります。おそらくご存知のように、ビルドのたびにビルド フォルダーにファイルが作成されます。このファイルには静的変数が含まれており、string.xml で宣言されたすべての変数には、いくつかの int 値を持つ独自の一意のIDがあり、このIDをコードで R.string として使用します。id . これが例外の理由です。システムは R.string を見つけようとします。指定された値に対応するid文字列ですが、ほとんどの場合明らかに失敗します。また、これが setText() が整数値を受け入れ、IDE が警告しない理由でもあります。場合によっては、偶然にIDに対応する値を持つことがあります。String
R.javaStringsome_variable. 例外はスローされず、変数値の代わりに予期しないテキスト (実際には 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-enとフォルダーのみを含むvalues-it(ただし、フォルダーstrings.xmlvaluesvalues-deフォルダーもありません) そのようなアプリを実行しようとするとします。この場合、アプリはvalues-de\strings.xml最初に検索しようとしますが失敗し、次にデフォルトを使用しようとしてvalues\strings.xmlもう一度失敗するため、 throwing でクラッシュしResources$NotFoundExceptionます。
この問題の修正は、前に述べたように、デフォルトを提供することstrings.xmlですres\valuesサポートされていないロケールの場合、デフォルトのロケールが使用されます (通常は英語)。もう 1 つの方法は、次のように、サポートされていないロケールのデバイスでアプリを実行する場合に、実行時にアプリに適切な既定のロケールを設定することです (たとえば、アプリケーション拡張クラス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 に答える