Search code examples
androidandroid-room

Why does the UI stop when running database.clearAllTables() in IO?


   @Query("DELETE FROM tableName")
    suspend fun resetData()
    fun startAllDataReset() = viewModelScope.launch(Dispatchers.IO) {
        dao.resetData()
    }

I initially deleted it as a delete query, but this method also stopped the ui.

    fun startAllDataReset() = viewModelScope.launch(Dispatchers.IO) {
        database.clearAllTables()
    }

The second time I tried this method also stops the ui. It stops for about 20 seconds, and then the ui starts working again, and I don't understand this part. Even if it worked on ui thread, there is less than 10 data on my table, and there seems to be no reason to operate for this long.


I also checked that the ui stopped when I deleted the datastore update and the room together.

    override suspend fun resetUserInfo() {
        userDatastore.updateData {
            it.toBuilder()
                .setId("")
                ....
                .build()
        }

        tokensDatastore.updateData {
            it.toBuilder()
                .setAccessToken("")
                .setRefreshToken("")
                .build()
        }
    }
    fun startAllDataReset() = viewModelScope.launch(Dispatchers.IO) {
        launch { authRepository.dbReset() }.join()

        authRepository.resetUserInfo()
    }

If you give enough delay, the ui stop will not occur and all the data will be reset wherever you want. Does anyone know why??

    fun startAllDataReset() = viewModelScope.launch(Dispatchers.IO) {
        launch { authRepository.dbReset() }.join()

        delay(5000)
        authRepository.resetUserInfo()

    }

Please tell me how I can write better code without any delay :)


Solution

  • Try to use suspend in your methods.

    @Query("DELETE FROM tableName")
    suspend fun resetData()
    

    Then the reset of that database should be suspend too

    suspend fun resetDB() {
        dao.resetData()
    }
    

    Also add the suspend modifier as you were doing, this is correct

    suspend fun resetUserInfo(userDatastore: DataStore<UserPreferences>, tokensDatastore: DataStore<TokenPreferences>) {
        userDatastore.updateData {
            it.toBuilder()
                .setId("")
                // ... other fields
                .build()
        }
    
        tokensDatastore.updateData {
            it.toBuilder()
                .setAccessToken("")
                .setRefreshToken("")
                .build()
        }
    }
    

    Then your startDataReset method should be

    fun startAllDataReset(authRepository: AuthRepository, userDatastore: DataStore<UserPreferences>, tokensDatastore: DataStore<TokenPreferences>) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                authRepository.resetDB()
            }
            
            resetUserInfo(userDatastore, tokensDatastore)
        }
    }
    

    Edit

    I guess the problem is in the launch you doing, you should use withContext and then do the launch. You are doing a launch(Dispatchers.IO) but then creating another launch that is not using the Dispatchers.IO, so your code would look like this to make it work and avoid the delay.

    fun startAllDataReset() = viewModelScope.launch {
        withContext(Dispatchers.IO) {
            launch { authRepository.dbReset() }.join()
        }
    
        withContext(Dispatchers.IO) {
            authRepository.resetUserInfo()
        }
    }
    

    If this still not working, try this one :

    fun startAllDataReset() = viewModelScope.launch {
        withContext(Dispatchers.IO) {
            authRepository.dbReset()
            authRepository.resetUserInfo()
        }
    }