androidkotlinandroid-viewmodelkotlin-flow

Trigger kotlin flow again on pull-to-refresh


I'm currently facing the following problem and hope someone might be able to help:

I have a flow in my ViewModel that provides me with some data. Now I would like this data to be reloaded on pull-to-refresh from ui, but I'm not sure what's the best method to re-trigger the flow or to reload the data.

Perhaps an example will illustrate what I mean:

I have the following ViewModel:

class MyViewModel(
 getSomeDataUsecase : GetSomeDataUseCase
): ViewModel(){
  val myData:Flow<SomeData> = getSomeDataUsecase() // <-- this returns a flow and emits the data

  fun refreshData(){
    // TODO: retrigger "getSomeDataUsecase" to load new data and provide them at "myData"
  }
}

Now I want to trigger the query getSomeDataUsecase again on pull-to-refresh, this should be done via the method refreshData. From there, however, I don't know how best to proceed.

Has anyone had the same problem? I would be interested to know how you solved it.

Thanks in advance :)


Solution

  • How you are using flows now is not how they should be used. You are using flows as a callback for an individual request. A flow should be a subscription and anytime data changes it is submitted to the flow.

    Using your code above this is how it should be

    class MyViewModel(
     getSomeDataUsecase : GetSomeDataUseCase
    ): ViewModel(){
      private val _mutableMyData:MutabelStateFLow<SomeData> = MutableStateFlow<SomeData>(initialData)
      val myData:StateFlow<SomeData> = _mutableMyData.asStateFlow()
    
      suspend fun refreshData(){
        val newData = getSomeDataUsecase()
        _mutableMyData.emit(newData)
      }
    }
    

    Then in your activity somewhere you collect your flow

    suspend fun listenForFlowUpdates(){
        viewModel.myData.collect{data ->
            //Called when new data is submitted to the flow
            //Update UI and stop your pull to refresh or whatever else
        }
    }
    

    Then all you have to do is call the refreshData() in your viewmodel from anywhere and you should get data