java - 使用改造从服务器获取数据之前显示进度条

标签 java android kotlin

我正在使用 Retrofit、coroutine、livedata、mvvm 等开发在线购物应用程序
我想在从服务器获取数据几秒钟之前显示进度条
如果我有一个 api 请求,我可以显示这一点,但在这个应用程序中我有多个请求
在这种情况下我应该怎么做我应该如何显示进度条?

API服务

 @GET("homeslider.php")
suspend fun getSliderImages(): Response<List<Model.Slider>>

@GET("amazingoffer.php")
suspend fun getAmazingProduct(): Response<List<Model.AmazingProduct>>

@GET("handsImages.php")
suspend fun getHandsFreeData(
    @Query(
        "handsfree_id"
    ) handsfree_id: Int
): Response<List<Model.HandsFreeImages>>

@GET("handsfreemoreinfo.php")
suspend fun gethandsfreemoreinfo(): Response<List<Model.HandsFreeMore>>


@GET("wristmetadata.php")
suspend fun getWristWatchMetaData(
    @Query(
        "wrist_id"
    ) wrist_id: Int
): Response<List<Model.WristWatch>>

存储库

 fun getSliderImages(): LiveData<List<Model.Slider>> {
    val data = MutableLiveData<List<Model.Slider>>()
    val job = Job()
    applicationScope.launch(IO + job) {
        val response = api.getSliderImages()
        withContext(Main + SupervisorJob(job)) {
            data.value = response.body()
        }
        job.complete()
        job.cancel()
    }
    return data
}

fun getAmazingOffer(): LiveData<List<Model.AmazingProduct>> {
    val data = MutableLiveData<List<Model.AmazingProduct>>()
    val job = Job()
    applicationScope.launch(IO + job) {
        val response = api.getAmazingProduct()
        withContext(Main + SupervisorJob(job)) {
            data.value = response.body()
        }
        job.complete()
        job.cancel()
    }
    return data
}

fun getHandsFreeData(handsree_id: Int): LiveData<List<Model.HandsFreeImages>> {

    val dfData = MutableLiveData<List<Model.HandsFreeImages>>()

    val job = Job()
    applicationScope.launch(IO + job) {


        val response = api.getHandsFreeData(handsree_id)

        withContext(Main + SupervisorJob(job)) {
            dfData.value = response.body()

        }
        job.complete()
        job.cancel()

    }
    return dfData
}

fun getHandsFreeMore(): LiveData<List<Model.HandsFreeMore>> {

    val data = MutableLiveData<List<Model.HandsFreeMore>>()
    val job = Job()
    applicationScope.launch(IO + job) {

        val response = api.gethandsfreemoreinfo()


        withContext(Main + SupervisorJob(job)) {

            data.value = response.body()

        }
        job.complete()
        job.cancel()
    }

    return data
}

View 模型

fun getSliderImages() = repository.getSliderImages()

fun getAmazingOffer() = repository.getAmazingOffer()

fun recieveAdvertise() = repository.recieveAdvertise()

fun dailyShoes(context: Context) = repository.getDailyShoes(context)

我会感谢你的帮助

最佳答案

我忍不住注意到您的存储库包含大量重复代码。这里要了解的第一点是,Repository 中的所有逻辑通常都在 ViewModel 中。第二件事是您正在使用 applicationScope 来启动协程,这通常是使用可用的 viewModelScope(负责取消)对象来完成在每个 viewModel 中。

因此,首先我们必须处理重复的代码并将其移至 ViewModel。所以你的 viewModel 现在看起来像

class YourViewModel: ViewModel() {
    // Your other init code, repo creation etc

    // Live data objects for progressBar and error, we will observe these in Fragment/Activity
    val showProgress: MutableLiveData<Boolean> = MutableLiveData()
    val errorMessage: MutableLiveData<String> = MutableLiveData()

    /**
      * A Generic api caller, which updates the given live data object with the api result 
      * and internally takes care of progress bar visibility. */
    private fun <T> callApiAndPost(liveData: MutableLiveData<T>,
                                   apiCall: () -> Response<T> ) = viewModelScope.launch {
        try{
            showProgress.postValue(true)   // Show prgress bar when api call is active
            if(result.code() == 200) { liveData.postValue(result.body())  }
            else{ errorMessage.postValue("Network call failed, try again") }
            showProgress.postValue(false)
        }
        catch (e: Exception){
            errorMessage.postValue("Network call failed, try again")
            showProgress.postValue(false)
        }
    }
    
    /******** Now all your API call methods should be called as *************/

    // First declare the live data object which will contain the api result
    val sliderData: MutableLiveData<List<Model.Slider>> = MutableLiveData()

    // Now call the API as
    fun getSliderImages() = callApiAndPost(sliderData) {
        repository.getSliderImages()
    }
}

之后,从存储库中删除所有逻辑,并使其简单地调用网络方法

suspend fun getSliderImages() = api.getSliderImages()   // simply delegate to network layer

最后要显示进度条,只需观察 Activity 中的 showProgress LiveData 对象/ fragment

viewModel.showProgress.observer(this, Observer{
    progressBar.visibility = if(it) View.VISIBLE else View.GONE
}

关于java - 使用改造从服务器获取数据之前显示进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68548658/

相关文章:

java - AsyncTask 在 doinbackground() 上抛出错误 "Caused by java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.Void[]"

android - findViewById(R.id.tabhost) 始终返回 null

android - 如何将文档快照(复杂对象)保存到共享首选项或文件?

java - 发现需要灵感时出错 : certificate_unknown and SSLHandshakeException on Payara

java - JETT 模板引擎不支持集合列表,而是支持 Java 实体类列表

android - 将 fragment 添加到对话框

android - Kotlin readBytes() 永远不会完成

java - 减少TomcatDeployer的间隔

java - 运行时的动态表达式求值器

android - 如何获取手机上所有已安装的应用程序?