Android Kotlin Room插入数据报错:无法在主线程访问数据库如何解决?
问题根因
报错的核心原因是你的DAO层写操作方法没有加suspend修饰,Room默认会要求这类数据库操作在子线程执行,哪怕你在外层包裹了协程,只要协程运行在主线程,调用非suspend的DAO方法依然会直接在主线程操作数据库,触发主线程阻塞报错。
修复步骤
- 修改DAO层接口,给非返回Flow/LiveData的数据库操作加上
suspend修饰
@Dao interface AccountConfigurationDao { @Query("SELECT * FROM accountconfiguration LIMIT 1") fun get(): Flow<AccountConfiguration> // 返回Flow的方法无需加suspend,Room会自动在后台线程发射数据 @Query("DELETE FROM accountconfiguration") suspend fun clear() // 写操作加suspend修饰 @Insert suspend fun insert(account_configuration: AccountConfiguration) // 写操作加suspend修饰 }
- 回滚你对ViewModel的错误修改,不需要给
insert方法加suspend,保持原有写法即可
// 无需加suspend,协程生命周期由viewModelScope管控更安全 fun insert(account_configuration: AccountConfiguration) = viewModelScope.launch { repository.update(account_configuration) }
- 视图层
save方法不需要做任何调整,直接调用viewModel.insert即可,不需要额外加lifecycleScope.launch包裹。
补充说明
DAO层的写操作加了suspend之后,Room会自动将这类操作调度到后台IO线程执行,不需要你手动切换线程,在默认运行在主线程的viewModelScope中调用也不会阻塞UI,viewModelScope会在ViewModel销毁时自动取消所有未完成的协程,避免内存泄漏。
内容的提问来源于stack exchange,提问作者bux
相关产品推荐
相关产品推荐

