调用主线程后,会议室数据库操作不会崩溃

时间:2019-12-20 05:41:23

标签: android kotlin android-room kotlin-coroutines

我正在使用Coroutines对我的db数据库执行Room操作 我已经为协程创建了一个助手,如下所示:

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的主线程之后,数据也已成功插入而不是崩溃了?

1 个答案:

答案 0 :(得分:0)

有关深入解答,请查看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房间定义将永远不会在应用程序线程上执行。