Search code examples
androidkotlinandroid-roomkotlin-flow

Android doing too much work on its main thread when collecting Flow


I have a local database function that returns the list of users in Flow format. Flow<List<User>>. The home screen only displays the latest list of users. When launching the app and pre-populating the database the flow receives the empty list first and then the updated list as the pre-population completes.

This is causing the Android to do too much work on its main thread and skipping the frames to render.

viewModelScope.launch {
 dao.getUsers().collect {
   userList.value = it
 }
}

Solution

  • The performance can be improved if we somehow only process the latest data as in the above-mentioned case, we don't need each emitted list of users, we only required, the latest list of users. So that we don't waste resources on processing each emitted list.

    Kotlin Flow has another operator known as collectLatest{} which is a bit different from collect{}.

    1. collect{} - This will collect each emitted data.
    2. collectLatest{} - This will cancel the collector when a new value is emitted.
    viewModelScope.launch {
     dao.getUsers().collectLatest {
       userList.value = it
     }
    }
    

    If we need to collect only the non-empty list, we can simply filter out the empty emitted list.

    viewModelScope.launch {
     dao.getUsers()
      .filter { it.isNotEmpty() }
      .collectLatest {
        userList.value = it
     }
    }