Chcę odczytać ciągi z xml
pliku, zanim zrobię coś innego, jak setText
na widżetach, więc jak mogę to zrobić bez obiektu aktywności do wywołaniagetResources()
?
Chcę odczytać ciągi z xml
pliku, zanim zrobię coś innego, jak setText
na widżetach, więc jak mogę to zrobić bez obiektu aktywności do wywołaniagetResources()
?
Odpowiedzi:
Application
, na przykładpublic class App extends Application {
android:name
atrybut swojego <application>
tagu w, AndroidManifest.xml
aby wskazywał na twoją nową klasę, npandroid:name=".App"
onCreate()
metodzie instancji aplikacji zapisz kontekst (np. this
) W statycznym polu o nazwie mContext
i utwórz statyczną metodę, która zwraca to pole, np . getContext()
:Tak to powinno wyglądać:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Teraz możesz użyć: App.getContext()
kiedy chcesz uzyskać kontekst, a następnie getResources()
(lub App.getContext().getResources()
).
Tylko dla zasobów systemowych!
Posługiwać się
Resources.getSystem().getString(android.R.string.cancel)
Możesz ich używać wszędzie w swojej aplikacji, nawet w deklaracjach stałych statycznych!
Toast
na przykład, uzyskanie SharedPreference
instancji, otwarcie bazy danych, jak mówi mój nauczyciel języka łacińskiego: i tak dalej ).
Moje rozwiązanie Kotlin polega na użyciu statycznego kontekstu aplikacji:
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
I klasa Strings, której używam wszędzie:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
Możesz więc mieć czysty sposób uzyskiwania ciągów zasobów
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
Proszę, nie usuwaj tej odpowiedzi, pozwól mi ją zachować.
Strings
było pomocne.
Jest też inna możliwość. Ładuję shadery OpenGl z takich zasobów:
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);
}
Jak widać, możesz uzyskać dostęp do dowolnego zasobu w ścieżce /res/...
Zmień aClass
do swojej klasy. Tak też ładuję zasoby w testach (androidTests)
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;
}
}
Zainicjuj Singleton w swojej Application
podklasie:
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);
}
}
Jeśli się nie mylę, to daje ci to podpięcie do applicationContext wszędzie, wywołuj to za pomocą. ApplicationContextSingleton.getInstance.getApplicationContext();
Nie powinieneś tego czyścić w żadnym momencie, ponieważ kiedy aplikacja się zamyka, to i tak się z tym wiąże.
Pamiętaj o aktualizacji, AndroidManifest.xml
aby używać tej Application
podklasy:
<?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"
>
Teraz powinno być możliwe użycie ApplicationContextSingleton.getInstance (). GetApplicationContext (). GetResources () z dowolnego miejsca, także z bardzo niewielu miejsc, w których podklasy aplikacji nie mogą.
Daj mi znać, jeśli zauważysz coś nie tak, dziękuję. :)
Inne rozwiązanie:
Jeśli masz statyczną podklasę w niestatycznej klasie zewnętrznej, możesz uzyskać dostęp do zasobów z podklasy poprzez statyczne zmienne w klasie zewnętrznej, które są inicjowane podczas tworzenia klasy zewnętrznej. Lubić
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
Użyłem go dla funkcji getPageTitle (pozycja int) statycznego FragmentPagerAdapter w ramach mojej FragmentActivity, która jest przydatna ze względu na I8N.
Używam App.getRes()
zamiast App.getContext().getResources()
(jak odpowiedział @Cristian)
Jest bardzo prosty w użyciu w dowolnym miejscu w kodzie!
Oto wyjątkowe rozwiązanie, dzięki któremu możesz uzyskać dostęp do zasobów z dowolnego miejsca, na przykładUtil class
.
(1) Utwórz lub edytuj swoją Application
klasę.
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) Dodaj pole nazwy do swojego manifest.xml
<application
tagu. (lub Pomiń to, jeśli już tam jest)
<application
android:name=".App"
...
>
...
</application>
Teraz możesz już iść.
App.getRes().getString(R.string.some_id)
dowolnym miejscu kodu.Myślę, że jest więcej możliwości. Ale czasami korzystam z tego rozwiązania. (pełne dane globalne):
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();
Ładuję moduł cieniujący dla openGL ES z funkcji statycznej.
Pamiętaj, że w nazwie pliku i katalogu musisz używać małych liter, w przeciwnym razie operacja się nie powiedzie
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();
}
Używam API poziomu 27 i znalazłem najlepsze rozwiązanie po zmaganiach przez około dwa dni. Jeśli chcesz odczytać plik xml z klasy, która nie pochodzi od Activity lub Application, wykonaj następujące czynności.
Umieść plik testdata.xml w katalogu zasobów.
Napisz poniższy kod, aby uzyskać przeanalizowany dokument 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);
W swojej klasie, w której implementujesz funkcję statyczną , możesz wywołać metodę private \ public z tej klasy. Metoda private \ public może uzyskać dostęp do getResources .
na przykład:
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));
}
}
az innych zajęć możesz zadzwonić:
Text.setColor('some EditText you initialized');
jeśli masz kontekst, mam na myśli wnętrze;
public void onReceive(Context context, Intent intent){
}
możesz użyć tego kodu, aby uzyskać zasoby:
context.getResources().getString(R.string.app_name);