Ich möchte Strings aus einer xml
-Datei lesen, bevor ich etwas anderes wie setText
für Widgets erledige. Wie kann ich das tun, ohne dass ein Aktivitätsobjekt getResources()
aufruft?
Application
NAME _ , zum Beispiel public class App extends Application {
Android:name
-Attribut Ihres <application>
-Tags im AndroidManifest.xml
, um auf Ihre neue Klasse zu verweisen, z. Android:name=".App"
onCreate()
Ihrer App-Instanz Ihren Kontext (z. B. this
name__) in einem statischen Feld mit dem Namen mContext
und erstellen Sie eine statische Methode, die dieses Feld zurückgibt, z. getContext()
:So sollte es aussehen:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Jetzt können Sie Folgendes verwenden: App.getContext()
, wann immer Sie einen Kontext abrufen möchten, und dann getResources()
(oder App.getContext().getResources()
).
Benutzen
Resources.getSystem().getString(Android.R.string.cancel)
Sie können sie überall in Ihrer Anwendung verwenden, selbst in Deklarationen statischer Konstanten! Aber nur für Systemressourcen!
Es gibt auch eine andere Möglichkeit. Ich lade OpenGl-Shader aus folgenden Ressourcen:
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);
}
Wie Sie sehen, können Sie auf jede Ressource im Pfad /res/...
.__ zugreifen. Ändern Sie aClass
in Ihre Klasse. Dies auch wie ich Ressourcen in Tests lade (androidTests)
The Singleton:
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;
}
}
Initialisieren Sie das Singleton in Ihrer Application
-Unterklasse:
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);
}
}
Wenn ich mich nicht irre, haben Sie überall einen Link zu applicationContext. Rufen Sie es mit ApplicationContextSingleton.getInstance.getApplicationContext();
.__ auf. Sie sollten dies an keiner Stelle löschen, da beim Schließen der Anwendung dies sowieso damit einhergeht.
Denken Sie daran, AndroidManifest.xml
zu aktualisieren, um diese Application
-Unterklasse zu verwenden:
<?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"
>
Jetzt sollten Sie ApplicationContextSingleton.getInstance (). GetApplicationContext (). GetResources () von überall aus verwenden können, auch an den wenigen Stellen, an denen Anwendungsunterklassen nicht funktionieren.
Bitte lassen Sie mich wissen, wenn Sie hier etwas Falsches sehen, danke. :)
Eine andere Lösung:
Wenn Sie eine statische Unterklasse in einer nicht statischen äußeren Klasse haben, können Sie von der Unterklasse aus über statische Variablen in der äußeren Klasse auf die Ressourcen zugreifen, die Sie beim Erstellen der äußeren Klasse initialisieren. Mögen
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
Ich habe es für die getPageTitle (int position) -Funktion des statischen FragmentPagerAdapter innerhalb meiner FragmentActivity verwendet, was wegen I8N nützlich ist.
Ich lade Shader für openGL ES von der statischen Funktion.
Denken Sie daran, dass Sie für Ihren Datei- und Verzeichnisnamen Kleinbuchstaben verwenden müssen, da sonst die Operation fehlschlägt
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() : "";
}
...
}
Ich mag Abkürzungen.
Ich benutze App.getRes()
anstelle von App.getContext().getResources()
(wie @Cristian geantwortet hat)
Was? Es ist sehr einfach, überall in Ihrer App zu verwenden!
Hier ist eine unique-Lösung, mit der Sie von überall auf Ressourcen wie Util class
zugreifen können.
(1) Erstellen oder bearbeiten Sie Ihre Application
-Klasse.
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 getResourses() {
return res;
}
}
(2) Fügen Sie Ihrem manifest.xml
<application
-Tag ein Namensfeld hinzu. (oder überspringen, wenn schon dort)
<application
Android:name=".App"
...
>
...
</application>
Jetzt bist du gut zu gehen. Verwenden Sie App.getRes().getString(R.string.some_id)
überall in der App.
public Static Resources mResources;
@Override
public void onCreate()
{
mResources = getResources();
}
Ich denke, es ist mehr möglich ... Aber manchmal benutze ich diese Lösung. (voll global):
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();
In Ihrer Klasse, in der Sie die Funktion static implementieren, können Sie eine private\public - Methode aus dieser Klasse aufrufen. Die private\public-Methode kann auf die getResources zugreifen.
zum Beispiel:
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));
}
}
und aus einer anderen Klasse\Aktivität können Sie anrufen:
Text.setColor('some EditText you initialized');
Ich benutze API Level 27 und habe nach rund zwei Tagen Schwierigkeiten gefunden. Wenn Sie eine XML-Datei aus einer Klasse lesen möchten, die nicht von Activity oder Application abgeleitet ist, gehen Sie wie folgt vor.
Legen Sie die Datei testdata.xml im Assets-Verzeichnis ab.
Schreiben Sie den folgenden Code, um das testdata-Dokument zu analysieren.
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);
wenn Sie einen Kontext haben, meine ich innen;
public void onReceive(Context context, Intent intent){
}
sie können diesen Code verwenden, um Ressourcen zu erhalten:
context.getResources().getString(R.string.app_name);