我很难在我的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/Activity
和SyncAdapter
中使用相同的productDao
对象,以便在插入新产品时触发LiveData,否则将不会触发。
所以,要获得相同的AppDatabase
,我必须得到相同的(即单身)ContentProvider
。
我知道这可以使用ContentProvider
来实现,这是在插入新数据时自动触发的。但我真的想尝试新的Android架构组件。
或者使用from ast import literal_eval as make_tuple
...
d = {make_tuple(k): d[k] for k in d}
是实现此用例的唯一正确方法吗?
答案 0 :(得分:4)
当您希望在不同的Threads
之间进行简单的沟通时,您需要处于相同的过程中。
在AndroidManifest.xml
中,您可以指定一个名为android:process=":processName"
的属性,可用于活动,服务(与SyncAdapters相关),内容提供商和广播接收器,可帮助您超越单个进程的堆(内存)默认限制。
这些是总结的PRO / CONS:
多进程PRO:你有更多的内存来运行你的应用程序,如果a 进程崩溃它不会崩溃其他的。
多进程CONS: 让流程变得困难(但并非不可能) 彼此沟通,但显然你不能分享它们之间的状态(在你的情况下,状态是单身)
为了深入理解,您应该阅读this article和this 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)
}