当前位置: 首页 > 知识库问答 >
问题:

"无法访问主线程上的数据库,因为它可能会长时间锁定用户界面。"我的协程出错

杨学真
2023-03-14

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

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)
        }
    }
}

但我还是犯了这个错误:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

在我上面的协程调用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()
    }

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

共有3个答案

浦德明
2023-03-14

您好,这个问题是因为数据库必须在主线程上运行。因此,您必须将这行代码添加到数据库部分

Room.databaseBuilder(context.getApplicationContext(),
            DataBaseTextChat.class, Constants.DB_TEXT_CHAT)
            .allowMainThreadQueries()
            .addCallback(roomCallBack).build();
钦宏义
2023-03-14

你不能使用调度器。Main用于长时间运行的任务。你必须使用调度器。IO对于数据库操作,如下所示:

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



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

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)
        }
    }
}
葛胡媚
2023-03-14

错误表示它不应该在主线程上运行。数据库操作(以及其他形式的IO)可能需要很长时间,应该在后台运行。

你应该使用调度员。IO是为运行IO操作而设计的。

 类似资料: