Quiero leer cadenas de un xml
archivo antes de hacer cualquier otra cosa como setText
en widgets, entonces, ¿cómo puedo hacer eso sin un objeto de actividad al que invocar getResources()
?
Quiero leer cadenas de un xml
archivo antes de hacer cualquier otra cosa como setText
en widgets, entonces, ¿cómo puedo hacer eso sin un objeto de actividad al que invocar getResources()
?
Respuestas:
Application
, por ejemplopublic class App extends Application {
android:name
atributo de su <application>
etiqueta en AndroidManifest.xml
para apuntar a su nueva clase, por ejemploandroid:name=".App"
onCreate()
método de la instancia de su aplicación, guarde su contexto (por ejemplo this
) en un campo estático llamado mContext
y cree un método estático que devuelva este campo, por ejemplo getContext()
:Así es como debería verse:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Ahora puede usar: App.getContext()
cuando quiera obtener un contexto, y luego getResources()
(o App.getContext().getResources()
).
¡Solo para recursos del sistema!
Utilizar
Resources.getSystem().getString(android.R.string.cancel)
¡Puede usarlos en cualquier lugar de su aplicación, incluso en declaraciones de constantes estáticas!
Toast
por ejemplo, obtener una SharedPreference
instancia, abrir una base de datos, como dice mi profesor de lengua latina: etcétera ).
Mi solución de Kotlin es usar un contexto de aplicación estático:
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
Y la clase Strings, que uso en todas partes:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
Para que pueda tener una forma limpia de obtener cadenas de recursos
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
Por favor, no elimine esta respuesta, déjame guardar una.
Strings
fue útil.
También hay otra posibilidad. Cargo sombreadores OpenGl de recursos como este:
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);
}
Como puede ver, puede acceder a cualquier recurso en la ruta /res/...
Cambiar aClass
a su clase. Así también cómo cargo recursos en pruebas (androidTests)
El 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;
}
}
Inicialice el Singleton en su Application
subclase:
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);
}
}
Si no me equivoco, esto le da un enlace al applicationContext en todas partes, llámelo ApplicationContextSingleton.getInstance.getApplicationContext();
llámelo No debería tener que borrar esto en ningún momento, ya que cuando la aplicación se cierra, esto va de todos modos.
Recuerde actualizar AndroidManifest.xml
para usar esta Application
subclase:
<?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"
>
Ahora debería poder usar ApplicationContextSingleton.getInstance (). GetApplicationContext (). GetResources () desde cualquier lugar, también los pocos lugares donde las subclases de aplicaciones no pueden.
Avísame si ves algo mal aquí, gracias. :)
Otra solución:
Si tiene una subclase estática en una clase externa no estática, puede acceder a los recursos desde dentro de la subclase a través de variables estáticas en la clase externa, que inicializa en la creación de la clase externa. Me gusta
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
Lo utilicé para la función getPageTitle (int position) del FragmentPagerAdapter estático dentro de mi FragmentActivity que es útil debido a I8N.
Yo uso en App.getRes()
lugar de App.getContext().getResources()
(como @Cristian respondió)
¡Es muy fácil de usar en cualquier parte de su código!
Así que aquí hay una solución única mediante la cual puede acceder a los recursos desde cualquier lugar Util class
.
(1) Crea o edita tu Application
clase.
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) Agregue el campo de nombre a su manifest.xml
<application
etiqueta. (o Omita esto si ya está allí)
<application
android:name=".App"
...
>
...
</application>
Ahora estás listo para irte.
App.getRes().getString(R.string.some_id)
en cualquier parte del código.Creo que es posible más. Pero a veces, uso esta solución. (global completo):
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();
Cargo shader para openGL ES desde la función estática.
Recuerde que debe usar minúsculas para su archivo y nombre de directorio, de lo contrario, la operación fallará
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();
}
Estoy usando API nivel 27 y encontré la mejor solución después de luchar durante unos dos días. Si desea leer un archivo xml de una clase que no se deriva de Actividad o Aplicación, haga lo siguiente.
Coloque el archivo testdata.xml dentro del directorio de activos.
Escriba el siguiente código para analizar el 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);
En su clase, donde implementa la función estática , puede llamar a un método privado \ público desde esta clase. El método privado \ público puede acceder a getResources .
por ejemplo:
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));
}
}
y desde otra clase \ actividad, puedes llamar a:
Text.setColor('some EditText you initialized');
si tienes un contexto, quiero decir adentro;
public void onReceive(Context context, Intent intent){
}
puedes usar este código para obtener recursos:
context.getResources().getString(R.string.app_name);