アクティビティが作成される前に、getString()
を使用してリソースから文字列を取得し、文字列配列に割り当てようとしています。
_private static final String[] MenuNames = {
Resources.getSystem().getString(R.string.LCMeterMenu),
Resources.getSystem().getString(R.string.FrecMenu),
Resources.getSystem().getString(R.string.LogicAnalyzerMenu),
"Prueba con achartengine",
Resources.getSystem().getString(R.string.BrazoMenu)
};
_
Resources.getSystem().getString(R.string.LCMeterMenu)
を使用すると、Eclipseは文句を言いませんが、実行時にエラーが発生します。
原因:Android.content.res.Resources $ NotFoundException:文字列リソースID#0x7f0a000a
しかし、onCreate()
の中に入れると:
_Log.i("StringR", "String: " + getString(R.string.LCMeterMenu));
_
文字列を取得しましたが、前に定義した最後の文字列に割り当てることができません。 getString()
の前にonCreate()
のみを使用すると、静的エラーメッセージが表示されます。グローバル変数のonCreate()
の前にリソースを使用するにはどうすればよいですか?
リソースから_static final
_フィールドを初期化することはできません。フィールドは、クラスが初期化されるときに初期化される必要があります。これは、実行時にアプリケーションリソースがバインドされる前に行われます。 (ちなみに、Resources.getSystem()
を使用できない理由は、その方法で取得したResources
オブジェクトには、アプリケーションリソースではなく、システムリソースのみが含まれているためです。)
アプリケーションリソースがバインドされる前にこれらの文字列を使用可能にする必要がある場合、実行する唯一の実用的なことは、文字列をコードに直接配置することです。ただし、「Androidの方法」はコードを整理することであるため、初期化はonCreate()
の最中(またはその後)にのみ行う必要があります。 onCreate()
で文字列配列を初期化するだけで、フィールドを静的または最終にする必要はありません。
文字列配列を特定のアクティビティに関連付けたくない場合は、Application
をサブクラス化し、アプリケーションクラスのonCreate()
メソッド内のリソースから配列を読み取ることができます。 (マニフェストでカスタムアプリケーションクラスを宣言する必要もあります。)ただし、 docs このようなアプローチはお勧めしません。 (配列はプライベートであるため、とにかく単一のアクティビティに密接に関連していると思われます。したがって、Application
サブクラスの使用は保証されていないようです。)
別の方法は、配列のシングルトンクラスを宣言することです。シングルトンアクセサ関数には、必要に応じてリソースを取得できるようにContext
が必要です。
_public class StringArray {
private static String[] theArray;
public static String[] getArray(Context context) {
if (theArray == null) {
theArray = context.getResources().getStringArray(R.array.my_strings);
}
return theArray;
}
}
_
(これは、文字列データが、彼の回答で提案された@JaiSoniのような_<string-array>
_リソースで定義されていることを前提としています。)ここでも、メンバーフィールドをfinal
として宣言することはできません。
いいえ、onCreate()
の前にリソースを使用することはできません。 onCreate()
を使用すると、getResources()
でResourcesのインスタンスを取得できます。ここですべての文字列を取得できます。また、文字列はstrings.xml
で定義することにより、すでに静的として宣言されています。
リソースにアクセスするための擬似コード、
Resources res = getResources();
String app_name = res.getString(R.string.app_name);
別のアプローチは、静的配列をリソース識別子(リソース自体ではなくすでに利用可能)で初期化することです。
private static final int[] MenuNames = {
R.string.LCMeterMenu,
R.string.FrecMenu,
...
};
このようにして、リソースのロードを実際に利用可能になるまで延期できます。
String s = getResources().getString(MenuNames[i]);
以下は、_static final
_などのXMLからAndroidの_strings.xml
_変数を初期化するための実用的なアプローチです。
1。_MyApplication.Java
_
_public abstract class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
/**
* Returns a "static" application context. Don't try to create dialogs on
* this, it's not gonna work!
*
* @return
*/
public static Context getContext() {
return context;
}
}
_
2。_AndroidManifest.xml
_
_<application
Android:name=".Android.application.MyApplication"
<!-- ... -->
</application>
_
3。アプリケーションコード(例:アクティビティ
_private static final String[] MenuNames = {
getContext().getString(R.string.LCMeterMenu),
getContext().getString(R.string.FrecMenu),
getContext().getString(R.string.LogicAnalyzerMenu),
"Prueba con achartengine",
getContext().getString(R.string.BrazoMenu)
};
protected static Context getContext() {
return MyApplication.getContext();
}
_
実例については、 AbstractApplication
および PreferencesServiceSharedPreferences
を参照してください。
このアプローチには欠点もあることに注意してください。
MyApplication.getContext()
の呼び出しは別のメソッドでラップされます。これは静的メソッドであるため、テストコードでオーバーライドするのは簡単ではありません。ただし、この目的には Powermock などのフレームワークを使用できます。NullPointerException
sに少し傾向があります。コンテキストがnull
になるとすぐに(たとえば、テストコード内で)、アプリケーションコードがクラッシュします。これを克服する1つのオプションは、コンストラクターで初期化を行うことです。コンストラクターでは、getContext()
return null
に反応できます( 例 を参照)。getString(int resId)
によって得られるものはすべて、アプリケーションにとってすでに定数になっています。なぜそれを別のfinal static
変数に保持する必要があるのですか。いつでも好きなときに読むことができますよね?