【发布时间】:2017-12-02 10:39:36
【问题描述】:
我正在努力将Room 用作我的SyncAdapter 中的单例。我使用 Kotlin。
我的房间课
@Database(entities = [(Product::class)], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun productDao(): ProductDao
companion object {
@Volatile private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context) : AppDatabase =
INSTANCE ?: synchronized(this) {
INSTANCE ?: buildDatabase(context.applicationContext)
.also {INSTANCE = it}
}
private fun buildDatabase(context: Context) =
Room
.databaseBuilder(context.applicationContext,
AppDatabase::class.java, "database.db")
.allowMainThreadQueries()
.build()
}
}
我这样检索数据库实例
val db = AppDatabase.getInstance(applicationContext)
而我的问题是,我在活动中总是得到两个不同的 AppDatabase 实例和 SyncAdapter。虽然在活动中AppDatabase 对象确实是单例.AppDatabase_Impl@3c9ff34d,并且对于每个 onPerformSync(),AppDatabase 也是单例.AppDatabase_Impl@7d7718d。
但正如你所看到的,它们是两个不同的对象。
谁能解释一下我在这里想念什么?
另一方面,我想要实现的目标可能在概念上是错误的。那么任何建议将不胜感激。
重点是在通过SynAdapter 从远程服务器插入新数据时使用LiveData 更新UI 组件。在这种情况下,我必须在 ViewModel/Activity 和 SyncAdapter 中使用相同的 productDao 对象,以便在插入新产品时触发 LiveData,否则不会触发。
因此,要获得相同的productDao,我必须获得相同的(即单例)AppDatabase。
我知道这可以使用ContentProvider 来实现,它会在插入新数据时自动触发。但我真的很想尝试新的 android 架构组件。
或者也许使用ContentProvider 是实现这个用例的唯一正确方法?
【问题讨论】:
-
你的
SyncAdapter和主线程在同一个进程吗? (这是您在清单中定义的内容) -
不,我的 SyncAdapter 使用 android:process=":sync"。我想我明白你的意思了:进程之间不共享单例?
-
是的,这可能是“唯一”的问题。让我们尝试删除
process行并将结果发布回此处。 -
从清单中删除单独全局进程的定义,即
android:process=":sync",起到了作用。现在我在活动和同步提供者之间拥有相同的数据库和 dao 对象。非常感谢你的帮助。但是,如果我只使用一个应用程序进程,此解决方案是否存在任何重大缺陷? -
我现在将发布一个完整的答案,让我解释一下;)
标签: android kotlin android-syncadapter android-room