Voglio leggere le stringhe da un xml
file prima di fare qualsiasi altra cosa come setText
sui widget, quindi come posso farlo senza un oggetto attività su cui chiamare getResources()
?
Voglio leggere le stringhe da un xml
file prima di fare qualsiasi altra cosa come setText
sui widget, quindi come posso farlo senza un oggetto attività su cui chiamare getResources()
?
Risposte:
Application
, ad esempiopublic class App extends Application {
android:name
attributo del <application>
tag in modo AndroidManifest.xml
che 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 mContext
e 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!
Toast
esempio, ottenere SharedPreference
un'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.
Strings
stata 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 aClass
nella 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 Application
sottoclasse:
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.xml
per utilizzare questa Application
sottoclasse:
<?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 Application
classe.
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
<application
tag. (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);