繁体   English   中英

如何在显示进度条的同时使用 Kotlin Coroutine.LiveData + Retrofit 进行 API 调用?

[英]How to use Kotlin Coroutine.LiveData + Retrofit for API call while showing a progress bar?

我正在尝试使用协程进行 API 调用并使用 MVVM 架构进行改造。 我想在等待 API 响应准备好(超时为 3 秒)时显示一个进度条。

视图模型中我使用 Coroutine.LiveData

class BootstrapViewModel: ViewModel() {

private val repository : ConfigRepository =
    ConfigRepository()

val configurations = liveData(Dispatchers.IO) {
    val retrievedConfigs = repository.getConfigurations(4)

    emit(retrievedConfigs)
}

}

到目前为止,我在活动中所做的只是模拟 API 调用以更新进度条:

launch {
        // simulate API call
        val configFetch = async(Dispatchers.IO) {
            while (progressState.value != 100) {
                progressState.postValue(progressState.value?.plus(1))
                delay(50)
            }
        }

        // suspend until fetch is finished or return null in 3 sec
        val result = withTimeoutOrNull(3000) { configFetch.await() }

        if (result != null) {
            // todo: process config... next steps
        } else {
            // cancel configFetch
            configFetch.cancel()

            // show error

        }
    }

我还可以观察如下实时数据并且工作正常:

bootstrapViewModel.configurations.observe(this, Observer {
        //response is ready
    })

一切正常分开。 但是,当我尝试在协程范围内使用 livedata 时,事情会变得混乱。 无论如何要await()协程 livedata (就像我为configFetch所做的那样)?

你可以这样做:

val _progressBarVisibility = MutableLiveData<Int>() // Use this with postValue
val progressBarVisibility: LiveData<Int> = _progressBarVisibility

val configurations = liveData(Dispatchers.IO) {
    _progressBarVisibility.postValue(View.VISIBLE)    

    // you can just stimulate API call with a delay() method
    delay(3000)    //3 seconds

    val retrievedConfigs = repository.getConfigurations(4)

    _progressBarVisibility.postValue(View.GONE)
    emit(retrievedConfigs)
}

之后在您的活动中:

viewModel.progressBarVisibility.observe(this, Observer{
  pbVisibilityView.visibity = it
}

如果您特别询问改造,这就是您可以做到的。

在你DataApi接口,您只需标记方法suspend ED:

interface DataApi{
  @GET("endpointHere")
  suspend fun getData() : Result<Data>
}

其余的就像我上面描述的那样。 只需将getConfigurations(4)替换为getData()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM