android - 调用主线程后,房间数据库操作不会崩溃
问题描述
我用来对我的数据库Coroutines
执行db
操作Room
我已经为 Coroutines 创建了一个帮助程序,如下所示
object Coroutines {
fun main(work: suspend(() -> Unit)) = CoroutineScope(Dispatchers.Main).launch {
work()
}
fun io(work: suspend(() -> Unit)) = CoroutineScope(Dispatchers.IO).launch {
work()
}
}
以下是我在主线程上调用插入操作的代码
class LocalListViewModel(private val localVideoRepository: LocalVideoRepository) : ViewModel() {
val localVideos = MutableLiveData<ArrayList<LocalVideo?>?>()
fun insertAllLocalVideo() {
Coroutines.main {
localVideoRepository.insertLocalVideo(localVideos.value)
}
}
}
class LocalVideoRepository(private val db: AppDatabase) {
suspend fun insertLocalVideo(localVideos: ArrayList<LocalVideo?>?) =
db.getLocalVideoDao().insertLocalVideos(localVideos)
}
@Dao
interface LocalVideoDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertLocalVideos(localVideoList: ArrayList<LocalVideo?>?)
}
@Database(entities = [LocalVideo::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun getLocalVideoDao(): LocalVideoDao
companion object {
@Volatile
private var instance: AppDatabase? = null
private val LOCK = Any()
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
instance ?: buildDatabase(context).also { instance = it }
}
private fun buildDatabase(context: Context) = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
context.getString(R.string.psplayer_db)
).build()
}
}
我不明白的是,即使在调用主线程之后Coroutines
,数据也会成功插入,而不是崩溃?
解决方案
要获得深入的答案,请查看CoroutinesRoom.execute
帮助程序:
suspend fun <R> execute(
db: RoomDatabase,
inTransaction: Boolean,
callable: Callable<R>
): R {
if (db.isOpen && db.inTransaction()) {
return callable.call()
}
// Use the transaction dispatcher if we are on a transaction coroutine, otherwise
// use the database dispatchers.
val context = coroutineContext[TransactionElement]?.transactionDispatcher
?: if (inTransaction) db.transactionDispatcher else db.queryDispatcher
return withContext(context) {
callable.call()
}
}
除非它已经在事务中,否则它总是将实际查询的执行转移到 IO 优化的调度程序上。因此,无论调用上下文如何,suspend
房间定义都不会在应用程序线程上执行。
推荐阅读
- java - 在 Spring Boot 中可分页
- python - 如何从 WTForms 中删除建议
- javascript - 使用 vue 根据元素 ui 树中的文件夹选择过滤文件
- r - 访问Rstudio中具有“useMethod(”packagefunction“)的函数的整个源代码?
- c++ - 在 C++ 中引用 string::string 中的任何字符
- delphi - 如何确定程序是否仅接受文件或文件列表作为参数?
- mongodb - 在构面内完成计数文档时返回空数组
- asp.net - 如何下载带有链接的 aspnetForm 页面
- php - 我正在尝试获取自动创建的用户 ID
- reactjs - 在此处获取父元素语法错误。找不到?