【问题标题】:How to scope a Database to a User using Dagger Hilt and Room?如何使用 Dagger Hilt 和 Room 将数据库范围限定为用户?
【发布时间】:2021-04-04 08:36:47
【问题描述】:

我正在尝试根据他们登录的用户 ID 提供不同的数据库,以便每个用户都可以拥有自己的数据库,如果您使用不同的帐户登录。我不想提供“所有者”字段,我尝试过但不喜欢它。

现在的问题是,数据库的范围仅限于应用程序范围,因此一旦用户注销并重新登录,就不会重新创建数据库。只有在重新启动应用程序时才会创建正确的数据库。

如何使用 Hilt 实现这种行为?

这就是现在的样子:

@InstallIn(SingletonComponent::class)
@Module
object ModuleDatabase {

    @Provides
    @Singleton
    fun provideAppDatabase(
        @ApplicationContext context: Context,
        userManager: UserManager,
    ): MyRoomDatabase {
        return Room.databaseBuilder(context, MyRoomDatabase::class.java, LOCAL_DATABASE_NAME + "_${userManager.loggedInUid()}")
            .addMigrations(...)
            .fallbackToDestructiveMigration()
            .build()
    }
}

【问题讨论】:

  • 我猜你可以使用@Named注入。但我不确定结果如何。
  • 不完全确定这应该如何工作
  • developer.android.com/training/dependency-injection/… 勾选这个。我认为您可以使用带有数据库名称的 @Named 注释而不是 Qualifier 注释。它仍然是一个 Singleton,但它会针对该数据库名称创建一个实例,并且可以说注销并使用新用户登录,名称将被更改,它将创建该 DB 的新 Singleton 实例。目前这只是一个理论,我从未使用过多个数据库。

标签: android dagger-2 android-jetpack dagger-hilt


【解决方案1】:

原来我需要创建一个符合要求的自定义 Hilt Component:

(请记住,这不适用于 WorkManager)

更新:它实际上是通过避免 Hilt Singleton 作用域并自己构建它来工作的。这也适用于 WorkManager,因为 WorkManager 可以访问 SingletonComponents 中的依赖项。

它基本上是这样工作的:

@InstallIn(SingletonComponent::class)
@Module
object ModuleDatabase {

    private var databaseName: String by Delegates.observable(LOCAL_DATABASE_NAME) { _, oldValue, newValue ->
        if (oldValue != newValue) {
            databaseConnection?.let {
                if (it.isOpen) {
                    it.close()
                }
                databaseConnection = null
                // new connection opens with new name
            }
        }
    }

    private var databaseConnection: TemporyRoomDatabase? = null

    private fun buildDatabase(context: Context, name: String): TemporyRoomDatabase {
        Timber.e("Building database $databaseName")
        return Room.databaseBuilder(context, TemporyRoomDatabase::class.java, name)
            .addMigrations(*TemporyRoomDatabase_Migrations.build())
            .fallbackToDestructiveMigration()
            .build()
    }

    private fun getDatabaseConnection(context: Context, newDatabaseName: String): TemporyRoomDatabase {
        return if (databaseName != newDatabaseName) {
            databaseName = newDatabaseName
            buildDatabase(context, databaseName).also {
                databaseConnection = it
            }
        } else {
            // use existing connection
            Timber.e("Reusing database $databaseName")
            databaseConnection ?: buildDatabase(context, databaseName)
        }
    }

    @Provides
    fun provideAppDatabase(
        @ApplicationContext context: Context,
        userManager: UserManager,
    ): TemporyRoomDatabase {
        return getDatabaseConnection(context, LOCAL_DATABASE_NAME + "_${userManager.loggedInUidOrNull()}")
    }
}

【讨论】:

    猜你喜欢
    • 2020-11-18
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多