“无法访问主线程上的数据库,因为它可能长时间锁定UI。” 我的协程错误

Zor*_*gan 1 android kotlin android-room kotlin-coroutines

我的协程正在主线程上运行,这是在我的协程上下文中指定的:

class ClickPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs), CoroutineScope, View.OnClickListener {

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main

override fun onClick(v: View?) {
    when (key){
        "logout" -> {
            CoroutineScope(coroutineContext).launch {
                CustomApplication.database?.clearAllTables()
                Log.d("MapFragment", "Cleared Tables")
            }
            if (Profile.getCurrentProfile() != null) LoginManager.getInstance().logOut()
            FirebaseAuth.getInstance().signOut()
            val intent = Intent(context, MainActivity::class.java)
            context.startActivity(intent)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但我仍然收到此错误:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
Run Code Online (Sandbox Code Playgroud)

在我上面对数据库的协程调用CustomApplication.database?.clearAllTables()Room

这是我的CustomApplication

class CustomApplication : Application() {

    companion object {
        var database: AppDatabase? = null
    }

    override fun onCreate() {
        super.onCreate()
        CustomApplication.database = Room.databaseBuilder(this, AppDatabase::class.java, "AppDatabase").build()
    }
Run Code Online (Sandbox Code Playgroud)

如果我的协程上下文在主线程上运行,为什么仍会出现错误?

psh*_*ger 6

该错误表明它不应在主线程上运行。数据库操作(以及其他所有形式的IO)可能会花费很长时间,因此应在后台运行。

您应该使用Dispatchers.IO专门用于运行IO操作的软件。

  • 现在可以将 DAO 函数标记为挂起函数。那么你就不需要使用Dispatchers.IO来调用它了。与必须在协程顶层包装阻塞调用相比,这是一个更干净的解决方案。 (2认同)