SyncAdapter中的Singleton Room数据库触发LiveData

时间:2017-12-02 10:39:36

标签: android kotlin android-syncadapter android-room

我很难在我的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对象确实是单身AppDatabase,但对于每个onPerformSync(),.AppDatabase_Impl@7d7718d也是单身LiveData。 但正如你所看到的,它们是两个不同的对象。 任何人都可以解释我在这里想念的东西吗?

另一方面,也许我在想要实现的目标上在概念上是错误的。那么任何建议都会受到赞赏。

关键是当通过SynAdapter从远程服务器插入新数据时,使用productDao更新UI组件。在这种情况下,我必须在ViewModel/ActivitySyncAdapter中使用相同的productDao对象,以便在插入新产品时触发LiveData,否则将不会触发。 所以,要获得相同的AppDatabase,我必须得到相同的(即单身)ContentProvider

我知道这可以使用ContentProvider来实现,这是在插入新数据时自动触发的。但我真的想尝试新的Android架构组件。 或者使用from ast import literal_eval as make_tuple ... d = {make_tuple(k): d[k] for k in d} 是实现此用例的唯一正确方法吗?

2 个答案:

答案 0 :(得分:4)

当您希望在不同的Threads之间进行简单的沟通时,您需要处于相同的过程中。

AndroidManifest.xml中,您可以指定一个名为android:process=":processName"的属性,可用于活动服务(与SyncAdapters相关),内容提供商广播接收器,可帮助您超越单个进程的堆(内存)默认限制。

这些是总结的PRO / CONS:

  

多进程PRO:你有更多的内存来运行你的应用程序,如果a   进程崩溃它不会崩溃其他的。

     

多进程CONS:   让流程变得困难(但并非不可能)   彼此沟通,但显然你不能分享它们之间的状态(在你的情况下,状态是单身)

为了深入理解,您应该阅读this articlethis good answer

我的建议:如果您的应用程序不是那么复杂并且您没有内存问题,我建议您从单一流程方法开始。如果您想要从应用程序中分离更新数据的SyncAdapter,或者在开发中的某个时刻发现与单个进程相关的瓶颈或崩溃,您可以切换到多进程,删除直接LiveData并使用ContentProvider沟通数据变化。

答案 1 :(得分:0)

使用dagger2:

class MyApplication : Application(){

    val component: AppComponent by lazy {
        DaggerAppComponent.builder().appModule(AppModule(this)).build()
    }

    @Inject
    lateinit var database : AppDatabase

    override fun onCreate() {
        super.onCreate()
        component.inject(this)
    }

}
@Singleton
@Component(modules = arrayOf(
        AppModule::class
))
interface AppComponent {
   fun inject(app: MyApplication)
}

@Module
class AppModule constructor(private val context: Context) {

@Provides
@Singleton
fun providesDatabase() = Room.databaseBuilder(context, AppDatabase::class.java, "mydb.db").build()

}

来自活动:

@Inject lateinit var mRoomDatabase: AppDatabase

override fun onCreate(savedInstanceState: Bundle?) {
     super.onCreate(savedInstanceState)
     (application as MyApplication).component.inject(this)
}