xml
ウィジェットで他のことをする前にファイルから文字列を読みたいのですがsetText
、アクティビティオブジェクトを呼び出さずにそれを行うにはどうすればよいgetResources()
ですか?
16 に答える
Application
たとえば、のサブクラスを作成しますpublic class App extends Application {
- 新しいクラスを指すようにタグの
android:name
属性を設定します。例:<application>
AndroidManifest.xml
android:name=".App"
onCreate()
アプリインスタンスのメソッドで、コンテキスト(例this
)をという名前の静的フィールドに保存しmContext
、このフィールドを返す静的メソッドを作成します。例getContext()
:
これはそれがどのように見えるべきかです:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
これで、次を使用できます。App.getContext()
コンテキストを取得するときはいつでも、次にgetResources()
(またはApp.getContext().getResources()
)。
システムリソースのみ!
使用する
Resources.getSystem().getString(android.R.string.cancel)
静的定数宣言でも、アプリケーションのどこでも使用できます。
私のKotlinソリューションは、静的なアプリケーションコンテキストを使用することです。
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
そして、私がどこでも使用しているStringsクラス:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
したがって、リソース文字列を取得するためのクリーンな方法を使用できます
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
この回答は削除しないでください。そのままにしておきます。
ショートカット
私はApp.getRes()
代わりに使用しますApp.getContext().getResources()
(@Cristianが答えたように)
コードのどこでも使用するのは非常に簡単です!
したがって、ここに、のようなどこからでもリソースにアクセスできる独自のソリューションUtil class
があります。
(1)クラスを作成または編集しますApplication
。
import android.app.Application;
import android.content.res.Resources;
public class App extends Application {
private static App mInstance;
private static Resources res;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
res = getResources();
}
public static App getInstance() {
return mInstance;
}
public static Resources getRes() {
return res;
}
}
manifest.xml
<application
(2)タグに名前フィールドを追加します。(または、すでに存在する場合はこれをスキップします)
<application
android:name=".App"
...
>
...
</application>
今、あなたは行ってもいいです。
App.getRes().getString(R.string.some_id)
コード内のどこでも使用できます。
別の可能性もあります。次のようなリソースからOpenGlシェーダーをロードします。
static private String vertexShaderCode;
static private String fragmentShaderCode;
static {
vertexShaderCode = readResourceAsString("/res/raw/vertex_shader.glsl");
fragmentShaderCode = readResourceAsString("/res/raw/fragment_shader.glsl");
}
private static String readResourceAsString(String path) {
Exception innerException;
Class<? extends FloorPlanRenderer> aClass = FloorPlanRenderer.class;
InputStream inputStream = aClass.getResourceAsStream(path);
byte[] bytes;
try {
bytes = new byte[inputStream.available()];
inputStream.read(bytes);
return new String(bytes);
} catch (IOException e) {
e.printStackTrace();
innerException = e;
}
throw new RuntimeException("Cannot load shader code from resources.", innerException);
}
/res/...
ご覧のとおり、クラスへのパス変更で任意のリソースにアクセスできますaClass
。これは、テストでリソースをロードする方法でもあります(androidTests)
シングルトン:
package com.domain.packagename;
import android.content.Context;
/**
* Created by Versa on 10.09.15.
*/
public class ApplicationContextSingleton {
private static PrefsContextSingleton mInstance;
private Context context;
public static ApplicationContextSingleton getInstance() {
if (mInstance == null) mInstance = getSync();
return mInstance;
}
private static synchronized ApplicationContextSingleton getSync() {
if (mInstance == null) mInstance = new PrefsContextSingleton();
return mInstance;
}
public void initialize(Context context) {
this.context = context;
}
public Context getApplicationContext() {
return context;
}
}
Application
サブクラスでシングルトンを初期化します。
package com.domain.packagename;
import android.app.Application;
/**
* Created by Versa on 25.08.15.
*/
public class mApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ApplicationContextSingleton.getInstance().initialize(this);
}
}
私が間違っていない場合、これはどこでもapplicationContextへのフックを提供し、それを呼び出しますApplicationContextSingleton.getInstance.getApplicationContext();
。アプリケーションが閉じるとき、これはとにかくそれに伴うので、いつでもこれをクリアする必要はありません。
AndroidManifest.xml
このApplication
サブクラスを使用するように更新することを忘れないでください。
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.domain.packagename"
>
<application
android:allowBackup="true"
android:name=".mApplication" <!-- This is the important line -->
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:icon="@drawable/app_icon"
>
これで、ApplicationContextSingleton.getInstance()。getApplicationContext()。getResources()をどこからでも使用できるようになります。また、アプリケーションサブクラスが使用できない場所もごくわずかです。
ここで何か問題がありましたらお知らせください。ありがとうございます。:)
別の解決策:
非静的外部クラスに静的サブクラスがある場合は、外部クラスの作成時に初期化する外部クラスの静的変数を介して、サブクラス内からリソースにアクセスできます。好き
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
これを、FragmentActivity内の静的FragmentPagerAdapterのgetPageTitle(int position)関数に使用しました。これは、I8Nのために便利です。
もっと多くの方法が可能だと思います。しかし、時々、私はこのソリューションを使用します。(フルグローバル):
import android.content.Context;
import <your package>.R;
public class XmlVar {
private XmlVar() {
}
private static String _write_success;
public static String write_success() {
return _write_success;
}
public static void Init(Context c) {
_write_success = c.getResources().getString(R.string.write_success);
}
}
//After activity created:
cont = this.getApplicationContext();
XmlVar.Init(cont);
//And use everywhere
XmlVar.write_success();
静的関数からopenGLESのシェーダーをロードします。
ファイル名とディレクトリ名には小文字を使用する必要があることを忘れないでください。そうしないと、操作が失敗します。
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
public static int loadShader() {
// Read file as input stream
InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");
// Convert input stream to string
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String shaderCode = s.hasNext() ? s.next() : "";
}
...
}
私はAPIレベル27を使用しており、約2日間苦労した後、最良の解決策を見つけました。ActivityまたはApplicationから派生していないクラスからxmlファイルを読み取りたい場合は、次のようにします。
testdata.xmlファイルをassetsディレクトリ内に配置します。
次のコードを記述して、testdataドキュメントを解析します。
InputStream inputStream = this.getClass().getResourceAsStream("/assets/testdata.xml"); // create a new DocumentBuilderFactory DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // use the factory to create a documentbuilder DocumentBuilder builder = factory.newDocumentBuilder(); // create a new document from input stream Document doc = builder.parse(inputStream);
コンテキストなしでImageresouseをInputStreamとして取得する:
Class<? extends MyClass> aClass = MyClass.class;
URL r = aClass.getResource("/res/raw/test.png");
URLConnection urlConnection = r.openConnection();
return new BufferedInputStream(urlConnection.getInputStream());
ファイルにディレクトリツリーが必要な場合は、それも機能します(アセットはサブディレクトリをサポートします)。
URL r = aClass.getResource("/assets/images/base/2.png");
なぜあなたは試さないのですか
Resources.getSystem().getString(R.string.foo);
これは、少し異なる別のアプローチです。
Application
他のソリューションが述べたようにクラスをサブクラス化し、のインスタンスへの静的参照を格納できますResources
。
アプリケーションクラスを作成し、メソッドでResources
変数を初期化します。onCreate
これは、アプリの起動時に呼び出されます。ここで使用WeakReference
して、このインスタンスを静的変数として格納した結果として発生する可能性のあるメモリリークを防ぐことができます(発生する可能性は非常に低いですが)
public class App extends Application {
private static WeakReference<Resources> res;
xmlリソース宣言から文字列を取得するだけでよいと述べたので、リソースインスタンスをカプセル化し、リークを防ぐために、このリソース変数を他のクラスに公開する必要はありません。したがって、参照をプライベート変数として格納できます。
この変数を次のように初期化することを忘れないでくださいonCreate
:
@Override
public void onCreate() {
super.onCreate();
res = new WeakReference<>(getResources());
}
また、タグの下でアプリケーションandroid:name
の.App
名前(または設定した他の名前)を宣言する必要があります。AndroidManifest.xml
application
<application android:name=".App"
........... other attributes here ...........
文字列リソースを取得する別の方法はResources
、他のクラス(またはContext
インスタンス)のインスタンスを使用するのではなくApp
、静的メソッドでこれを取得するクラスを取得することです。これにより、インスタンスがカプセル化/プライベートに保たれます。
クラスで静的メソッドを使用して、App
これらの値を取得できます(たとえば、デフォルトのメソッドと競合するため、getStringGlobal
呼び出さないでください)。getString
public static String getStringGlobal(@StringRes int resId) {
if (res != null && res.get() != null) {
return res.get().getString(resId);
} else {
// This should not happen, you should throw an exception here, or you can return a fallback string to ensure the app still runs
}
}
ご覧のとおり、のインスタンスが使用できない場合に備えて、エラー処理を追加することもできResources
ます(これは発生しないはずですが、念のため)。
次に、を呼び出すことで文字列リソースを取得できます
App.getStringGlobal(R.string./*your string resource name*/)
だからあなたのApp.java
:
public class App extends Application {
private static WeakReference<Resources> res;
@Override
public void onCreate() {
super.onCreate();
res = new WeakReference<>(getResources());
}
public static String getStringGlobal(@StringRes int resId) {
if (res != null && res.get() != null) {
return res.get().getString(resId);
} else {
// This should not happen(reference to Resources invalid), you should throw an exception here, or you can return a fallback string to ensure the app still runs
}
}
}
静的関数を実装するクラスでは、このクラスからprivate\publicメソッドを呼び出すことができます。private \ publicメソッドは、getResourcesにアクセスできます。
例えば:
public class Text {
public static void setColor(EditText et) {
et.resetColor(); // it works
// ERROR
et.setTextColor(getResources().getColor(R.color.Black)); // ERROR
}
// set the color to be black when reset
private void resetColor() {
setTextColor(getResources().getColor(R.color.Black));
}
}
そして他のclass\activityから、あなたは呼び出すことができます:
Text.setColor('some EditText you initialized');
あなたが文脈を持っているなら、私は内部を意味します。
public void onReceive(Context context, Intent intent){
}
このコードを使用してリソースを取得できます。
context.getResources().getString(R.string.app_name);
public Static Resources mResources;
@Override
public void onCreate()
{
mResources = getResources();
}