Voglio leggere le stringhe da un xmlfile prima di fare qualsiasi altra cosa come setTextsui widget, quindi come posso farlo senza un oggetto attività su cui chiamare getResources()?
Voglio leggere le stringhe da un xmlfile prima di fare qualsiasi altra cosa come setTextsui widget, quindi come posso farlo senza un oggetto attività su cui chiamare getResources()?
Risposte:
Application, ad esempiopublic class App extends Application {android:nameattributo del <application>tag in modo AndroidManifest.xmlche punti alla nuova classe, ad esandroid:name=".App"onCreate()metodo dell'istanza dell'app, salva il tuo contesto (ad esempio this) in un campo statico denominato mContexte crea un metodo statico che restituisca questo campo, ad esempio getContext():Ecco come dovrebbe apparire:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Ora puoi usare: App.getContext()ogni volta che vuoi ottenere un contesto, e poi getResources()(o App.getContext().getResources()).
Solo per risorse di sistema!
Uso
Resources.getSystem().getString(android.R.string.cancel)
Puoi usarli ovunque nella tua applicazione, anche nelle dichiarazioni di costanti statiche!
Toastesempio, ottenere SharedPreferenceun'istanza, aprire un database, come dice il mio insegnante di lingua latina: eccetera ).
La mia soluzione Kotlin è utilizzare un contesto di applicazione statico:
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
E la classe Strings, che uso ovunque:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
Quindi puoi avere un modo pulito di ottenere stringhe di risorse
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
Per favore, non cancellare questa risposta, lascia che ne conservi una.
Stringsstata utile.
C'è anche un'altra possibilità. Carico gli shader OpenGl da risorse come questa:
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);
}
Come puoi vedere, puoi accedere a qualsiasi risorsa nel percorso /res/...
Cambia aClassnella tua classe. Questo è anche il modo in cui carico le risorse nei test (androidTest)
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;
}
}
Inizializza il Singleton nella Applicationsottoclasse:
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);
}
}
Se non sbaglio, questo ti dà un gancio per applicationContext dappertutto, chiamalo con ApplicationContextSingleton.getInstance.getApplicationContext();
Non dovresti cancellarlo in nessun momento, come quando l'applicazione si chiude, questo va comunque con esso.
Ricorda di aggiornare AndroidManifest.xmlper utilizzare questa Applicationsottoclasse:
<?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"
>
Ora dovresti essere in grado di utilizzare ApplicationContextSingleton.getInstance (). GetApplicationContext (). GetResources () da qualsiasi luogo, anche i pochi posti in cui le sottoclassi delle applicazioni non possono.
Per favore fatemi sapere se vedete qualcosa di sbagliato qui, grazie. :)
Un'altra soluzione:
Se si dispone di una sottoclasse statica in una classe esterna non statica, è possibile accedere alle risorse all'interno della sottoclasse tramite variabili statiche nella classe esterna, inizializzata al momento della creazione della classe esterna. Piace
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
L'ho usato per la funzione getPageTitle (int position) del FragmentPagerAdapter statico nel mio FragmentActivity che è utile a causa di I8N.
Uso App.getRes()invece di App.getContext().getResources()(come ha risposto @Cristian)
È molto semplice da usare ovunque nel tuo codice!
Quindi ecco una soluzione unica con la quale puoi accedere alle risorse da qualsiasi luogo simile Util class.
(1) Crea o modifica la tua Applicationclasse.
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) Aggiungi il campo del nome al tuo manifest.xml <applicationtag. (o Salta se già presente)
<application
android:name=".App"
...
>
...
</application>
Ora sei a posto.
App.getRes().getString(R.string.some_id)ovunque nel codice.Penso che sia possibile più strada. Ma a volte, sto usando questa soluzione. (pieno globale):
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();
Carico shader per openGL ES dalla funzione statica.
Ricorda che devi usare le lettere minuscole per il nome del file e della directory, altrimenti l'operazione fallirà
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();
}
Sto usando il livello API 27 e ho trovato la soluzione migliore dopo aver lottato per circa due giorni. Se si desidera leggere un file XML da una classe che non deriva da attività o applicazione, procedere come segue.
Inserisci il file testdata.xml nella directory delle risorse.
Scrivi il seguente codice per ottenere l'analisi del documento 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);Nella tua classe, dove implementi la funzione statica , puoi chiamare un metodo privato \ pubblico da questa classe. Il metodo privato \ pubblico può accedere a getResources .
per esempio:
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));
}
}
e da un'altra classe \ attività, puoi chiamare:
Text.setColor('some EditText you initialized');
se hai un contesto, intendo dentro;
public void onReceive(Context context, Intent intent){
}
puoi usare questo codice per ottenere risorse:
context.getResources().getString(R.string.app_name);