I want to read strings from an xml
file before I do much of anything else like setText
on widgets, so how can I do that without an activity object to call getResources()
on?
问题:
回答1:
- Create a subclass of
Application
, for instancepublic class App extends Application {
- Set the
android:name
attribute of your<application>
tag in theAndroidManifest.xml
to point to your new class, e.g.android:name=\".App\"
- In the
onCreate()
method of your app instance, save your context (e.g.this
) to a static field namedmContext
and create a static method that returns this field, e.g.getContext()
:
This is how it should look:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Now you can use: App.getContext()
whenever you want to get a context, and then getResources()
(or App.getContext().getResources()
).
回答2:
Use
Resources.getSystem().getString(android.R.string.cancel)
You can use them everywhere in your application, even in static constants declarations! But for system resources only!
回答3:
The 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;
}
}
Initialize the Singleton in your Application
subclass:
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);
}
}
If I´m not wrong, this gives you a hook to applicationContext everywhere, call it with ApplicationContextSingleton.getInstance.getApplicationContext();
You shouldn´t need to clear this at any point, as when application closes, this goes with it anyway.
Remember to update AndroidManifest.xml
to use this Application
subclass:
<?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\"
>
Now you should be able to use ApplicationContextSingleton.getInstance().getApplicationContext().getResources() from anywhere, also the very few places where application subclasses can´t.
Please let me know if you see anything wrong here, thank you. :)
回答4:
There is also another possibilty. I load OpenGl shaders from resources like this:
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);
}
As you can see, you can access any resource in path /res/...
Change aClass
to your class. This also how I load resources in tests (androidTests)
回答5:
Another solution:
If you have a static subclass in a non-static outer class, you can access the resources from within the subclass via static variables in the outer class, which you initialise on creation of the outer class. Like
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
I used it for the getPageTitle(int position) Function of the static FragmentPagerAdapter within my FragmentActivity which is useful because of I8N.
回答6:
I think, more way is possible. But sometimes, I using this solution. (full global):
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();
回答7:
In your class, where you implement the static function, you can call a private\\public method from this class. The private\\public method can access the getResources.
for example:
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));
}
}
and from other class\\activity, you can call:
Text.setColor(\'some EditText you initialized\');
回答8:
if you have a context, i mean inside;
public void onReceive(Context context, Intent intent){
}
you can use this code to get resources:
context.getResources().getString(R.string.app_name);
回答9:
I like shortcuts.
I use App.getRes()
instead of App.getContext().getResources()
(as @Cristian answered)
What? It is very simple to use anywhere in your app!
So here is a unique solution by which you can access resources from anywhere like Util class
.
(1) Create or Edit your Application
class.
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) Add name field to your manifest.xml
<application
tag. (or Skip this if already there)
<application
android:name=\".App\"
...
>
...
</application>
Now you are good to go. Use App.getRes().getString(R.string.some_id)
anywhere in app.
回答10:
I load shader for openGL ES from static function.
Remember you must use lower case for your file and directory name, or else the operation will be failed
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() : \"\";
}
...
}
回答11:
public Static Resources mResources;
@Override
public void onCreate()
{
mResources = getResources();
}