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

时间:2019-12-03 12:21:18

标签: android kotlin retrofit android-livedata coroutine

我正在尝试使用协程进行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()是否有协程实时数据(就像我对 configFetch 所做的那样)?

1 个答案:

答案 0 :(得分:0)

您可以这样做:

val _progressBarVisibility = MutableLiveData<Int>()
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()