Ich möchte Zeichenfolgen aus einer xml
Datei lesen, bevor ich etwas anderes wie setText
Widgets mache. Wie kann ich das tun, ohne dass ein Aktivitätsobjekt aufgerufen werden muss getResources()
?
Ich möchte Zeichenfolgen aus einer xml
Datei lesen, bevor ich etwas anderes wie setText
Widgets mache. Wie kann ich das tun, ohne dass ein Aktivitätsobjekt aufgerufen werden muss getResources()
?
Antworten:
Application
zum Beispielpublic class App extends Application {
android:name
Attribut Ihres <application>
Tags in AndroidManifest.xml
, um auf Ihre neue Klasse zu verweisen, zandroid:name=".App"
onCreate()
Speichern Sie in der Methode Ihrer App-Instanz Ihren Kontext (z. B. this
) 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 verwenden: App.getContext()
wann immer Sie einen Kontext erhalten möchten, und dann getResources()
(oder App.getContext().getResources()
).
Nur für Systemressourcen!
Verwenden
Resources.getSystem().getString(android.R.string.cancel)
Sie können sie überall in Ihrer Anwendung verwenden, auch in Deklarationen für statische Konstanten!
Toast
z. B. eine SharedPreference
Instanz erstellen, eine Instanz abrufen, eine Datenbank öffnen, wie mein Lateinlehrer sagt: usw. ).
Meine Kotlin-Lösung besteht darin, einen statischen Anwendungskontext zu verwenden:
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
Und die Strings-Klasse, die ich überall benutze:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
So können Sie Ressourcen auf saubere Weise abrufen
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
Bitte löschen Sie diese Antwort nicht, lassen Sie mich eine behalten.
Strings
war sie hilfreich.
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/...
Ändern aClass
zu Ihrer Klasse zugreifen . So lade ich auch Ressourcen in Tests (androidTests)
Der 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 den 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, gibt Ihnen dies überall einen Haken an applicationContext. Rufen Sie ihn mit auf. ApplicationContextSingleton.getInstance.getApplicationContext();
Sie sollten dies zu keinem Zeitpunkt löschen müssen, da dies beim Schließen der Anwendung sowieso dazu gehört.
Denken Sie daran, ein Update durchzuführen AndroidManifest.xml
, 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 von den wenigen Stellen, an denen Anwendungsunterklassen dies nicht können.
Bitte lassen Sie mich wissen, wenn Sie hier etwas falsch sehen, danke. :) :)
Eine andere Lösung:
Wenn Sie eine statische Unterklasse in einer nicht statischen äußeren Klasse haben, können Sie über statische Variablen in der äußeren Klasse, die Sie beim Erstellen der äußeren Klasse initialisieren, von innerhalb der Unterklasse auf die Ressourcen zugreifen. 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 Funktion getPageTitle (int position) des statischen FragmentPagerAdapter in meiner FragmentActivity verwendet, die aufgrund von I8N nützlich ist.
Ich benutze App.getRes()
statt App.getContext().getResources()
(wie @Cristian antwortete)
Es ist sehr einfach, überall in Ihrem Code zu verwenden!
Hier ist eine einzigartige Lösung, mit der Sie von überall auf Ressourcen zugreifen können Util class
.
(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 Sie dies, wenn bereits vorhanden)
<application
android:name=".App"
...
>
...
</application>
Jetzt können Sie loslegen.
App.getRes().getString(R.string.some_id)
überall im Code.Ich denke, mehr Weg ist möglich. Aber manchmal benutze ich diese Lösung. (vollständig 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();
Ich lade den Shader für openGL ES aus der statischen Funktion.
Denken Sie daran, dass Sie für Ihren Datei- und Verzeichnisnamen Kleinbuchstaben verwenden müssen, da sonst der Vorgang 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() : "";
}
...
}
public Static Resources mResources;
@Override
public void onCreate()
{
mResources = getResources();
}
Ich verwende API Level 27 und habe die beste Lösung gefunden, nachdem ich ungefähr zwei Tage lang Probleme hatte. Wenn Sie eine XML-Datei aus einer Klasse lesen möchten, die nicht von Aktivität oder Anwendung abgeleitet ist, gehen Sie wie folgt vor.
Legen Sie die Datei testdata.xml im Assets-Verzeichnis ab.
Schreiben Sie den folgenden Code, um das Testdatendokument 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);
In Ihrer Klasse, in der Sie die statische Funktion implementieren , können Sie eine private \ public- Methode aus dieser Klasse aufrufen . Die private \ public-Methode kann auf die getResources zugreifen .
beispielsweise:
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 von einer anderen Klasse \ Aktivität aus können Sie Folgendes aufrufen:
Text.setColor('some EditText you initialized');
Wenn Sie einen Kontext haben, meine ich innen;
public void onReceive(Context context, Intent intent){
}
Mit diesem Code können Sie Ressourcen abrufen:
context.getResources().getString(R.string.app_name);