============ 问题 1 - 我有什么选择... ============== =
在 Android 中使用单例有很多陷阱。其中最重要的是 Android 管理您的应用程序的生命周期。因此,任何活动都可能随时被破坏。或者,如果出于其他目的需要内存,Android 甚至可能会选择终止您的进程。 Android 将恢复您的应用程序/活动,但是如果您什么都不做,状态就会丢失。在 process-kill 场景中,您有一个新的 VM 实例,并且 Singleton 对象中的任何状态都丢失了。当然,如果您仔细编码,则可以确保以正确的状态适当地重新创建这些。这可能很难且容易出错。
如果您需要应用中的任何 Activity 提供这些模型类,您可以采取几种更好的方法:
选项 1。
我。使用Intents 将对象从一个活动传递到另一个活动。这解决了“全球可用”的问题。这还需要您将模型类设为Parcelable 或可序列化。
ii.使用onSaveInstanceState 方法保存活动中对象的状态。在onCreate 方法中恢复状态。这个过程被描述为here。
这种方法的尴尬之处在于,在每次活动转换时始终写入和读取 Intent 所需的开销和额外代码。
选项 2
考虑让您的单例在每次写入时持久化其数据,并在每次读取时从持久化中读取。您可以使用多种持久性机制,包括:SharedPreferences、基本文件 I/O 和 SQL 数据库。这些选项在这里讨论:http://developer.android.com/guide/topics/data/data-storage.html。如果你走这条路,我个人发现 SharedPreferences 是最容易使用的。
这是一个如何完成的示例
public class User {
//---------------------
// Singleton implementation. Note this is just one of several styles
// of this pattern.
private static User instance = new User();
private User() {} // prevent instantiation
public User getUserInstance() { return instance; }
//---------------------
private String category = "user_bean_settings";
private String emailKey = "email";
private String nameKey = "name";
public String getEmail() {
return readStringProperty(emailKey);
}
public void setEmail(String email) {
writeStringProperty(emailKey, email);
}
public String getName() {
return readStringProperty(nameKey);
}
public void setName(String name) {
writeStringProperty(nameKey, name);
}
private String readStringProperty(String prop) {
Context context = getApplicationContext();
SharedPreferences prefs = context.getSharedPreferences(category, Context.MODE_PRIVATE);
return prefs.getString(prop, null);
}
private void writeStringProperty(String prop, String value) {
Context context = getApplicationContext();
SharedPreferences prefs = context.getSharedPreferences(category, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(prop, value);
editor.commit();
}
}
其中一个尴尬的部分是您需要有一个方便的上下文引用来访问 SharedPreferences。如何最好地做到这一点是你的电话。请记住,活动本身就是上下文,因此您始终可以通过它。有很多不同的方法来处理这个问题。
======= 问题 2 - dagger2 是创建单例的替代方法吗?... ==========
我查看了 Dagger 2,发现它是一个依赖注入框架。使用 DI 框架有很多好处(松散耦合、可测试性……)。您可以使用 Dagger(或其他 DI 框架,如 RoboGuice)来管理您的单例。如果这是您的唯一目标,我个人认为不值得额外的集成努力。但是,如果您想享受上面提到的 DI 的其他一些好处,那么可能值得您花时间。请记住,这些不是免费的,您仍然需要遵循良好的编码实践。无论如何,这似乎超出了问题的范围。