Android应用程序中,关于保存全局数据是使用Singletons还是Application对象的一些讨论:
(注明都是网上和书中摘录,为了好看的绿色,妄称原创,见谅!)
Singletons are a nightmare for testing and, if lazily initialized, will introduce "state indeterminism" with subtle side effects (which may suddenly surface when moving calls to getInstance() from one scope to another). Visibility has been mentioned as another problem, and since singletons imply "global" (= random) access to shared state, subtle bugs may arise when not properly synchronized in concurrent applications.
I consider it an anti-pattern, it's a bad object-oriented style often embraced by people coming from procedural languages like C, where it is common to maintain global state.
To come back to your question: Although the app context can be considered a singleton itself, it is framework-managed and has a well defined life-cycle, scope, and access path. Hence I believe that if you do need to manage app-global state, it should go here, nowhere else. For anything else, rethink if you really need a singleton object, or if it would also be possible to rewrite your singleton class to instead instantiate small, short-lived objects that perform the task at hand.
Android SDK关于Application类介绍提到的:
There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally usesContext.getApplicationContext() when first constructing the singleton.
而《Android in Practice》书中介绍的:
We’ll talk more about lifecycle in chapter 3, but the important thing to keep in mind with the Application object is that it’s created when the process for your application is created, and it isn’t bound to a particular Activity or Service. This means it’s a great and extremely simple way to hold onto and share nontrivial and nonpersistent data between activities and services within your application. By nontrivial and nonpersistent, we mean data that your application needs which would be cumbersome to pass around as Intent extras everywhere, and also isn’t appropriate for a file or database.
ANOTHER WAY TO SHARE IN-APP DATA Another good choice for nontrivial and nonpersistent data is a static singleton object. You have to be careful with statics, though. They don’t have a well-defined lifecycle, and it’s easy to hang onto a reference that could cause a memory leak. If you prefer statics over the Application object, that’s fine, but consider setting up and tearing down your static classes from the Application object, which does have a welldefined lifecycle, for the best of both worlds.
下面是一个使用Application的例子
The more general problem you are encountering is how to save state across several Activities and all parts of your application. A static variable (for instance, a singleton) is a common Java way of achieving this. I have found however, that a more elegant way in Android is to associate your state with the Application context.
As you know, each Activity is also a Context, which is information about its execution environment in the broadest sense. Your application also has a context, and Android guarantees that it will exist as a single instance across your application.
The way to do this is to create your own subclass of android.app.Application, and then specify that class in the application tag in your manifest. Now Android will automatically create an instance of that class and make it available for your entire application. You can access it from any context using the Context.getApplicationContext() method (Activity also provides a method getApplication() which has the exact same effect):
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
This has essentially the same effect as using a static variable or singleton, but integrates quite well into the existing Android framework. Note that this will not work across processes (should your app be one of the rare ones that has multiple processes).