如何使用 dagger2 设置和获取模型 class 的 Singleton 对象?

How to set and get Singleton object of a model class using dagger2?

要在 Android 应用程序中创建所有模型 classes 的单个实例,我有哪些选择?

我在下面添加了一个示例模型 classes

public class User
{
    private String email;
    private String name;
    public String getEmail()           {  return this.email;    }
    public void setEmail(String email) {  this.email = email;   }
    public String getName()            {  return this.name;    }
    public void setName(String name)   {  this.name = name;   }
}

我希望一旦数据存储在模型 Class 中,就可以在任何 activity、class 或片段中检索它。我应该使用单例,还是有更好的方法?

dagger2 在这种情况下可以工作吗? dagger2 是创建单例的替代方法吗?

谢谢

============ 问题 1 - 我有什么选择... ======= ========

在 Android 中使用单例有很多陷阱。其中最大的是 Android 管理应用程序的生命周期。因此任何 activity 都可以随时销毁。或者 Android 如果内存需要用于其他目的,甚至可能会选择终止您的进程。 Android 将恢复您的 app/activity,但是如果您什么都不做,状态就会丢失。在进程终止场景中,您有一个新的 VM 实例,并且 Singleton 对象中的任何状态都丢失了。当然,如果您小心编码,您可以确保以正确的状态适当地重新创建这些。这可能很难并且容易出错。

如果您需要这些模型 类 可以从您的应用中的任何 activity 获得,您可以采用几种更好的方法:

选项 1.

我。使用 Intents. This solves the "globally available" problem. This will also require you to make your model classes Parcelable 或可序列化将对象从 activity 传递到 activity。 二.使用 onSaveInstanceState 方法保存 activity 中对象的状态。恢复 onCreate 方法中的状态。此过程描述为 here

这种方法的尴尬之处在于每次 activity 转换时始终写入和读取 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();
    }
}

其中一个尴尬的部分是您需要有一个方便的 Context 引用才能访问 SharedPreferences。如何最好地做到这一点是你的决定。请记住,活动本身就是上下文,因此您始终可以传递它。有很多不同的方法来处理这个问题。

======= 问题 2 - dagger2 是创建单例的替代方法吗?... ==========

我查看了 Dagger 2,发现它是一个依赖注入框架。使用 DI 框架有很多好处(松散耦合、可测试性……)。您可以使用 Dagger(或其他 DI 框架,如 RoboGuice)来管理您的单例。如果那是您的 only objective,我个人认为不值得为集成付出额外的努力。但是,如果您想享受上面提到的 DI 的其他一些好处,那么它可能值得您花时间。请记住,这些都不是免费的,您仍然需要遵循良好的编码习惯。 Anways,这似乎超出了问题的范围。

A bound service 将是一个很好的解决方案。客户端会将其绑定到应用程序上下文,以便 "any activity, class, or fragment."

可以访问同一实例

此解决方案将避免必须序列化 to/from Intent 的开销。如果您不需要它,它还可以避免持久性的开销。