在拉动刷新时再次触发 kotlin 流程

问题描述 投票:0回答:2

我目前面临以下问题,希望有人能够提供帮助:

我的 ViewModel 中有一个

flow
,它为我提供了一些数据。现在我希望从 ui 上拉刷新时重新加载此数据,但我不确定重新触发流程或重新加载数据的最佳方法是什么。

也许有一个例子可以说明我的意思:

我有以下视图模型:

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

现在我想在下拉刷新时再次触发查询

getSomeDataUsecase
,这应该通过方法
refreshData
来完成。然而,从那里,我不知道如何最好地继续。

有人遇到同样的问题吗?我很想知道你是如何解决的。

提前致谢:)

android kotlin android-viewmodel kotlin-flow
2个回答
0
投票

您现在使用流程的方式并不是它们应该使用的方式。您正在使用流作为单个请求的回调。流程应该是订阅,并且任何时候数据更改都会提交到流程。

使用上面的代码应该是这样的

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

然后在您的活动中收集流量

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

然后你所要做的就是从任何地方调用视图模型中的

refreshData()
,你应该获取数据


0
投票

我不知道为什么我之前无法得到它,所以感谢大家的回复:D .

这是我现在处理手动触发刷新的解决方案:

class MyViewModel(
 getSomeDataUsecase : GetSomeDataUseCase
): ViewModel(){

  private val forceRefreshAction = MutableSharedFlow<Boolean>(
    extraBufferCapacity = 1,
    onBufferOverflow = BufferOverflow.DROP_OLDEST,
  )
 
  val myData:Flow<SomeData> = forceRefreshAction
    .onStart {
        emit(false)
    }
    .flatMapLatest { forceRefresh ->
        getSomeDataUsecase() // <-- this returns a flow and emits the data
    }
    .flowOn(dispatcher.io)
    .stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5000, replayExpirationMillis = 5000),
        initialValue = SomeData(),
    )

  fun refreshData(){
    forceRefreshAction.tryEmit(true) // <-- Called from UI on pull-to-refresh
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.