Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Cannot access database on the main thread since it may potentially lock the UI for a long period of time." error on my Coroutine

My Coroutine is running on the main thread, which i've specified in my Coroutine context:

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

But I'm still getting this error:

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

on my above Coroutine call CustomApplication.database?.clearAllTables() to my Room database.

Here is my 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()
    }

Why am I still getting the error if my coroutine context runs on the main thread?

like image 577
Zorgan Avatar asked Oct 17 '25 15:10

Zorgan


2 Answers

The error says that it should NOT run on the main thread. Database operations (and every other form of IO) can take a long time and should be run in the background.

You should use Dispatchers.IO which is designed for running IO operations.

like image 146
pshegger Avatar answered Oct 20 '25 06:10

pshegger


You can't use Dispatchers.Main for the long-running task. You have to use Dispatchers.IO for database operations, look likes:

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)
        }
    }
}
like image 31
Abu Noman Avatar answered Oct 20 '25 05:10

Abu Noman