Я хочу прочитати рядки з xml
файлу, перш ніж робити багато чого іншого, як setText
на віджетах, тож як я можу це зробити без об'єкта активності, щоб викликати getResources()
?
Я хочу прочитати рядки з xml
файлу, перш ніж робити багато чого іншого, як setText
на віджетах, тож як я можу це зробити без об'єкта активності, щоб викликати getResources()
?
Відповіді:
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 ).
Моє рішення Котліна полягає у використанні статичного контексту програми:
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
було корисно.
Є ще одна можливість. Я завантажую шаблони 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)
Сінглтон:
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) статичної FragmentPagerAdapter в рамках моєї FragmentActivity, що корисно через I8N.
Я використовую 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 getResourses() {
return res;
}
}
(2) Додати поле імені до свого manifest.xml
<application
тегу. (або пропустити це, якщо вже є)
<application
android:name=".App"
...
>
...
</application>
Тепер вам добре піти.
App.getRes().getString(R.string.some_id)
будь-де в коді.Думаю, можливий більше шлях. Але іноді я використовую це рішення. (повністю глобальний):
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() : "";
}
...
}
public Static Resources mResources;
@Override
public void onCreate()
{
mResources = getResources();
}
Я використовую API рівня 27 і знайшов найкраще рішення після боротьби протягом двох днів. Якщо ви хочете прочитати XML-файл із класу, який не походить від діяльності чи програми, то виконайте наступне.
Помістіть файл testdata.xml всередині каталогу активів.
Напишіть наступний код для розбору документа з тестовими даними.
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);
У вашому класі, де ви реалізуєте статичну функцію, ви можете викликати приватний \ 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);