Quero ler seqüências de caracteres de um xml
arquivo antes de fazer qualquer outra coisa como setText
nos widgets, então como posso fazer isso sem um objeto de atividade para chamar getResources()
?
Quero ler seqüências de caracteres de um xml
arquivo antes de fazer qualquer outra coisa como setText
nos widgets, então como posso fazer isso sem um objeto de atividade para chamar getResources()
?
Respostas:
Application
, por exemplopublic class App extends Application {
android:name
atributo da sua <application>
tag no AndroidManifest.xml
para apontar para sua nova classe, por exemploandroid:name=".App"
onCreate()
método da instância do aplicativo, salve o contexto (por exemplo this
) em um campo estático chamado mContext
e crie um método estático que retorne esse campo, por exemplo getContext()
:É assim que deve parecer:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Agora você pode usar: App.getContext()
sempre que quiser obter um contexto e, em seguida getResources()
(ou App.getContext().getResources()
).
Apenas para recursos do sistema!
Usar
Resources.getSystem().getString(android.R.string.cancel)
Você pode usá-los em qualquer lugar do seu aplicativo, mesmo em declarações de constantes estáticas!
Toast
instância, obter uma SharedPreference
instância, abrir um banco de dados, como meu professor de língua latina diz: et cetera ).
Minha solução Kotlin é usar um contexto de aplicativo estático:
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
E a classe Strings, que eu uso em qualquer lugar:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
Assim, você pode ter uma maneira limpa de obter cadeias de recursos
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
Por favor, não apague esta resposta, deixe-me manter uma.
Strings
foi útil.
Há também outra possibilidade. Eu carrego os shaders OpenGl a partir 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 você pode ver, você pode acessar qualquer recurso no caminho /res/...
Change aClass
para sua classe. Também é assim que eu carrego recursos em testes (androidTests)
O 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;
}
}
Inicialize o Singleton na sua Application
subclasse:
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 não estou errado, isso dá a você um gancho para o applicationContext em todos os lugares, chame-o com ApplicationContextSingleton.getInstance.getApplicationContext();
Você não precisa limpar isso a qualquer momento, pois quando o aplicativo é fechado, isso também acontece com ele.
Lembre-se de atualizar AndroidManifest.xml
para usar esta Application
subclasse:
<?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"
>
Agora você deve poder usar ApplicationContextSingleton.getInstance (). GetApplicationContext (). GetResources () de qualquer lugar, também os poucos lugares em que as subclasses de aplicativos não podem.
Avise-me se vir algo errado aqui, obrigado. :)
Outra solução:
Se você tiver uma subclasse estática em uma classe externa não estática, poderá acessar os recursos de dentro da subclasse por meio de variáveis estáticas na classe externa, que você inicializa na criação da classe externa. Gostar
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
Usei-o para a função getPageTitle (int position) do FragmentPagerAdapter estático em meu FragmentActivity, útil por causa do I8N.
Eu uso em App.getRes()
vez de App.getContext().getResources()
(como @ Cristian respondeu)
É muito simples de usar em qualquer lugar do seu código!
Então, aqui está uma solução exclusiva pela qual você pode acessar recursos de qualquer lugar Util class
.
(1) Crie ou edite sua Application
turma.
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) Adicione um campo de nome à sua manifest.xml
<application
tag. (ou Ignore se já estiver lá)
<application
android:name=".App"
...
>
...
</application>
Agora você está pronto para ir.
App.getRes().getString(R.string.some_id)
em qualquer lugar no código.Eu acho, de mais maneira é possível. Mas, às vezes, estou usando esta solução. (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();
Eu carrego o shader para o openGL ES a partir da função estática.
Lembre-se de que você deve usar letras minúsculas para o nome do arquivo e diretório, caso contrário a operação falhará
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();
}
Estou usando o nível 27 da API e encontrei a melhor solução depois de lutar por cerca de dois dias. Se você deseja ler um arquivo xml de uma classe que não deriva de Activity ou Application, faça o seguinte.
Coloque o arquivo testdata.xml no diretório de ativos.
Escreva o código a seguir para obter o documento testdata analisado.
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);
Na sua classe, onde você implementa a função estática , você pode chamar um método private \ public dessa classe. O método private \ public pode acessar os getResources .
por exemplo:
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 de outra classe \ atividade, você pode chamar:
Text.setColor('some EditText you initialized');
se você tem um contexto, quero dizer por dentro;
public void onReceive(Context context, Intent intent){
}
você pode usar este código para obter recursos:
context.getResources().getString(R.string.app_name);