Я хочу прочитать строки из файла xml
, прежде чем делать что-либо еще, например setText
для виджетов, так как же я могу сделать это без объекта действия, для которого вызывается getResources()
?
Как я могу получить содержимое ресурса из статического контекста?
Ответы (15)
- Создайте подкласс
Application
, напримерpublic class App extends Application {
- Установите атрибут
android:name
вашего тега<application>
вAndroidManifest.xml
, чтобы он указывал на ваш новый класс, например.android:name=".App"
- В методе
onCreate()
вашего экземпляра приложения сохраните свой контекст (например,this
) в статическом поле с именемmContext
и создайте статический метод, который возвращает это поле, например.getContext()
:
Вот как это должно выглядеть:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Теперь вы можете использовать: App.getContext()
всякий раз, когда хотите получить контекст, а затем getResources()
(или App.getContext().getResources()
).
Только для системных ресурсов!
Использовать
Resources.getSystem().getString(android.R.string.cancel)
Вы можете использовать их везде в своем приложении, даже в объявлениях статических констант!
Toast
, получение экземпляра SharedPreference
, открытие базы данных, как говорит мой учитель латинского языка: et cetera).
- person Cristian; 07.01.2012
R.string.my_own_string
НЕ является системным ресурсом. Так что этот ответ действительно не касается вопроса.
- person Sébastien; 17.04.2020
Мое решение Kotlin заключается в использовании статического контекста приложения:
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
И класс Strings, который я использую везде:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
Таким образом, у вас может быть чистый способ получения строк ресурсов
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
Пожалуйста, не удаляйте этот ответ, позвольте мне оставить его.
Strings
было полезно.
- person CoolMind; 24.04.2020
Есть и другая возможность. Я загружаю шейдеры OpenGl из таких ресурсов:
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);
}
Как видите, вы можете получить доступ к любому ресурсу по пути /res/...
Изменить aClass
на свой класс. Это также то, как я загружаю ресурсы в тесты (androidTests)
Ярлык
Я использую App.getRes()
вместо App.getContext().getResources()
(как ответил @Cristian)
Его очень просто использовать в любом месте вашего кода!
Итак, вот уникальное решение, с помощью которого вы можете получить доступ к ресурсам откуда угодно, например Util class
.
(1) Создайте или отредактируйте свой Application
класс.
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 getRes() {
return res;
}
}
(2) Добавьте поле имени в свой тег manifest.xml
<application
. (или пропустить, если уже есть)
<application
android:name=".App"
...
>
...
</application>
Теперь вы можете идти.
Используйте App.getRes().getString(R.string.some_id)
в любом месте кода.
getRes()
, а не getResources()
- person Khemraj Sharma; 04.08.2020
Синглтон:
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;
}
}
Инициализируйте Singleton в вашем подклассе Application
:
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);
}
}
Если я не ошибаюсь, это дает вам доступ к applicationContext везде, вызывайте его с помощью ApplicationContextSingleton.getInstance.getApplicationContext();
Вам не нужно очищать это в какой-либо момент, так как когда приложение закрывается, это все равно происходит.
Не забудьте обновить AndroidManifest.xml
, чтобы использовать этот подкласс Application
:
<?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"
>
Теперь вы должны иметь возможность использовать ApplicationContextSingleton.getInstance().getApplicationContext().getResources() из любого места, а также из очень немногих мест, где подклассы приложений не могут.
Пожалуйста, дайте мне знать, если вы видите что-то не так, спасибо. :)
Другое решение:
Если у вас есть статический подкласс в нестатическом внешнем классе, вы можете получить доступ к ресурсам внутри подкласса через статические переменные во внешнем классе, которые вы инициализируете при создании внешнего класса. Нравится
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
Я использовал его для функции getPageTitle(int position) статического FragmentPagerAdapter в моей FragmentActivity, что полезно из-за I8N.
Думаю, можно и по-другому. Но иногда я использую это решение. (полный глобальный):
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();
Я загружаю шейдер для openGL ES из статической функции.
Помните, что вы должны использовать нижний регистр для имени файла и каталога, иначе операция не будет выполнена.
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() : "";
}
...
}
Я использую уровень API 27 и нашел лучшее решение после двухдневной борьбы. Если вы хотите прочитать XML-файл из класса, который не является производным от Activity или Application, сделайте следующее.
Поместите файл testdata.xml в каталог с ресурсами.
Напишите следующий код, чтобы разобрать документ 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);
Получение изображения как InputStream без контекста:
Class<? extends MyClass> aClass = MyClass.class;
URL r = aClass.getResource("/res/raw/test.png");
URLConnection urlConnection = r.openConnection();
return new BufferedInputStream(urlConnection.getInputStream());
Если вам нужно дерево каталогов для ваших файлов, оно также будет работать (активы поддерживают подкаталоги):
URL r = aClass.getResource("/assets/images/base/2.png");
почему ты не пытаешься
Resources.getSystem().getString(R.string.foo);
В вашем классе, где вы реализуете функцию static, вы можете вызвать метод private\public из этого класса. Метод private\public может получить доступ к getResources.
например:
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));
}
}
и из другого класса \ деятельности вы можете позвонить:
Text.setColor('some EditText you initialized');
если у вас есть контекст, я имею в виду внутри;
public void onReceive(Context context, Intent intent){
}
вы можете использовать этот код для получения ресурсов:
context.getResources().getString(R.string.app_name);