Android使用 Combine 和 Stateflow同时调用多个API

Android使用 Combine 和 Stateflow同时调用多个API

Android使用 Combine 和 Stateflow同时调用多个API_第1张图片
在这里,我解释了如何将多个 API(或任何其他数据提供者)组合在一起以在 Android 应用程序中实现复杂的页面。

在当前的现代 Android 应用程序中,有时我们应该显示来自多个数据源的数据,所有数据的状态都很重要。

在本文中,我将 MVVM、Koin 和存储库模式与协程规则结合使用。

想象一下,我们想要设计一个页面来显示来自 API 1 和 API 2 的数据列表。它们应该组合起来显示数据,当每个数据都来自不同的存储库时,它会变得更加复杂。

或者即使每次数据发生变化,我们应该如何更新我们的页面?

Android使用 Combine 和 Stateflow同时调用多个API_第2张图片
Android使用 Combine 和 Stateflow同时调用多个API_第3张图片
假设我们有 3 个名为exchangeOverviewrollingPricewatchList的 API 调用,但最后我们只需要一个数据,我们将其称为fullList

private val exchangeOverView = MutableStateFlow<Result<ExchangeOverview>>(Result.Loading)
private val rollingPrice =
    MutableStateFlow<Result<HashMap<String, RollingPrice>>?>(Result.Loading)
private val watchList = MutableStateFlow<Result<List<Coin>>?>(Result.Loading)

结果类如下所示

sealed class Result<out T : Any> {
    data class Success<out T : Any>(val data: T?) : Result<T>()
    data class Error(val exception: String, val errorCode: Int) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

对于Stateflow的默认部分,我们使用Result.Loading,因为我们没有任何缓存(如果需要我们可以把它作为Stateflow的默认值)。

为什么不使用 Sharedflow

因为我们需要每个 API 的最后状态,并且我们想在多个新/旧页面中使用它,因此我们使用 Stateflow 而不是 Sharedflow

我们不知道所有 API 何时都成功,但我们知道希望所有 API 都准备就绪。
就是这样!这里我们的函数看起来像这样:

private suspend fun getExchangeOverview() {
    exchangeRepository.getExchangeOverview().collect { result ->
        when (result) {
            is Result.Loading -> {
                exchangeOverView.emit(Result.Loading)
            }

            is Result.Success -> {
                exchangeOverView.emit(Result.Success(result.data))
            }
            is Result.Error -> {
                exchangeOverView.emit(Result.Error(result.exception, result.errorCode))
            }
        }
    }
}

对于所有其他 API,我们使用的功能相同。

为了组合它们,我们使用下面的函数,当所有 API 都成功时我们只发出成功,并且 fof 失败和加载我们有自定义功能。

private fun combineData(): StateFlow<Result<List<SymbolsItem>>?>? =
    combine(
        exchangeOverView,
        rollingPrice,
        watchList
    ) { exchangeOverView, rollingPrice, wattchList ->
        if (exchangeOverView is Result.Success && rollingPrice is Result.Success && wattchList is Result.Success && currentUserState.value) {
val data = ourFunctionForUseAllDataToghether()
            Result.Success(data)
        } else if (exchangeOverView is Result.Error) {
            Result.Error(exchangeOverView.exception, exchangeOverView.errorCode)
        } else if (rollingPrice is Result.Error) {
            Result.Error(rollingPrice.exception, rollingPrice.errorCode)
        } else {
            Result.Loading
        }
    }.stateIn(viewModelScope, SharingStarted.Eagerly, null)
_fullDataStateFlow = combineData()

好的,我们的数据可以使用了。

在 Fragment/Activity 中我们调用了:

lifecycleScope.launchWhenResumed {
    viewModel.fullListData.collectLatest { result ->
        when (result) {
            is Result.Loading -> {
                shwoLoading()          
            }
            is Result.Success -> {
                showData()
            }
            is Result.Error -> {
                showError()
            }
        }
    }
}

Android使用 Combine 和 Stateflow同时调用多个API_第4张图片

参考

https://medium.com/@keyvan.nrz/call-multile-api-calls-with-combine-and-stateflow-1cf4ea4ac322

你可能感兴趣的:(Kotlin进阶,Android架构,android,kotlin,android,jetpack)