【问题标题】:How to set and get Singleton object of a model class using dagger2?如何使用 dagger2 设置和获取模型类的 Singleton 对象?
【发布时间】:2016-04-26 07:15:22
【问题描述】:

我有哪些选项可以在 Android 应用程序中创建所有模型类的单个实例?

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

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;   }
}

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

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

谢谢

【问题讨论】:

    标签: design-patterns dagger dagger-2


    【解决方案1】:

    ============ 问题 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 的其他一些好处,那么可能值得您花时间。请记住,这些不是免费的,您仍然需要遵循良好的编码实践。无论如何,这似乎超出了问题的范围。

    【讨论】:

    • 你能告诉我如何使用 dagger2 来避免单例吗?示例代码对我有很大帮助
    • 1) 抱歉,我不熟悉 dagger2。 2)对于选项#1,提供的链接应该有足够的信息,3)对于选项#2,我将在一分钟内发布一个示例......
    • 我做了一些修改: 1) 增强了示例以包括对单例模式的执行。 2) 简单介绍一下 Dagger 和其他 DI 框架。
    【解决方案2】:

    bound service 将是一个很好的解决方案。客户端会将其绑定到 Application 上下文,因此“任何活动、类或片段”都可以访问相同的实例。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 2019-03-30
      • 2017-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多