【问题标题】:Using Singleton within the Android Room Library在 Android 房间库中使用 Singleton
【发布时间】:2018-04-30 15:04:13
【问题描述】:

我一直被告知使用 Singleton 很糟糕。然而,Android Room 实现的每个示例似乎都使用了 Singleton 方法。有人可以解释一下为什么会这样吗?

谢谢

【问题讨论】:

  • 使用单例并不是一个坏习惯。对于特定情况,这可能是一个很好的做法,例如实例化数据库(这里看起来就是您的情况)。那么为什么使用它来实例化数据库是一个好习惯呢?数据库对象上的单例会阻止任何人两次实例化您的数据库对象,这可能会导致棘手的错误和性能下降。这可能是一个很好的做法,只是取决于您使用它的原因和方式。
  • 能否提供有关您在哪里看到使用 Singleton 实现 Android Room 的链接?
  • 他们有不少,但这个来自Google Code Lab
  • 我反对它的唯一原因是我一直被告知使用它们并不理想(难以测试,导致内存泄漏......)

标签: android design-patterns android-room android-architecture-components android-livedata


【解决方案1】:

有两种方式

1 ) 你应该使用匕首 2

2) 在作为类对象的抽象 RoomDatabase 类中创建方法

例子:

@Database(entities = { Repo.class }, version = 1)
public abstract class RepoDatabase extends RoomDatabase {

    private static final String DB_NAME = "repoDatabase.db";
    private static volatile RepoDatabase instance;

    static synchronized RepoDatabase getInstance(Context context) {
        if (instance == null) {
            instance = create(context);
        }
        return instance;
    }

private RepoDatabase() {};

    private static RepoDatabase create(final Context context) {
        return Room.databaseBuilder(
            context,
            RepoDatabase.class,
            DB_NAME).build();
    }

    public abstract RepoDao getRepoDao();
}

【讨论】:

  • 你能解释一下为什么getInstance()方法是“静态同步的”吗?
  • 已同步,因为可以在多线程场景中创建两个实例。静态应该解释自己
  • 如何访问实例?
  • 您可以通过这种方式获得访问权限:RepoDatabase.getInstance(context)
  • @NikhilVadoliya - 您忘记为getInstance() 添加public。默认是私有的
【解决方案2】:

单例被认为是邪恶的,因为滥用它们会使测试变得困难。如果被测试的代码出现并抓取了一个静态单例,那么该单例就变得难以模拟以进行测试。

为了缓解测试问题,您的代码不应该获得单例。始终将其作为构造函数参数接收或由 DI 框架注入。当然,DI 只是解决了问题,因为这样 DI 组件就变成了你的代码所获取的单例。但是你只需要弄清楚如何模拟 DI 组件而不是一堆其他的东西。

在 Android 上,Application 实际上是一个单例,因为每个虚拟机只创建一个实例。因此,它是托管其他单例(如 DI 组件)的好地方。

【讨论】:

    猜你喜欢
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    相关资源
    最近更新 更多