androidsqlitekotlinandroid-room

'Cannot access database on the main thread since it may potentially lock the UI for a long period of time' Also, I Accessed room using coroutine


Initially I directly accessed a viewModel funtion which launched a viewModel scope coroutine for the query I was running. That had the same error.

Then, I changed the viewModel function to a suspend function and called it from a coroutine in the fragment. that didn't work either.

So, I made it such that the function was called inside a coroutine which then ran another coroutine in the viewModel scope. That gave the same outcome.

I thought it might be too much load to call it during fragment creation. so I tried calling the viewModel function using a button onclick listener. again crashed.

I ran the same query in the database inspector where it worked fine. so, the query isn't the issue either.

In the below screenshot I have included every necessary detail regarding the issue. Just focus on the highlighted content. start from pass List Fragment(top-left tab). From there, a call to the viewModel function in the top right tab. from there the DAO right below it. then the data class below it.

Android studio screenshot - android studio screenshot

the viewModel function -

fun resetAllAccess(){
    viewModelScope.launch {
        passwordDao.resetAccessForAll()
    }
}

The DAO funtion -

@Query("UPDATE password_data SET access = 0 WHERE access = 1")
    fun resetAccessForAll()

Data class for the database -

@Entity(tableName = "password_data")
data class PasswordData(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    @ColumnInfo(name = "service_name") var serviceName: String,
    @ColumnInfo(name = "service_password") var servicePassword: String,
    @ColumnInfo(name = "is_an_application") var isAnApplication: Boolean = false,
    @ColumnInfo(name = "use_finger_print") var useFingerPrint: Boolean = true,
    @ColumnInfo(name = "access") var access: Boolean = false
)

the call being made from the fragment -

CoroutineScope(Dispatchers.IO).launch { viewModel.resetAllAccess() }

Solution

  • I replaced this funtion -

    fun resetAllAccess(){
        viewModelScope.launch {
            passwordDao.resetAccessForAll()
        }
    }
    

    -with

    fun resetAllAccess(){
            CoroutineScope(Dispatchers.IO).launch {
                passwordDao.resetAccessForAll()
            }
        }
    

    so now, it is no longer running on the main thread.