在所有联网请求完成或其中一个失败后如何执行操作?

时间:2019-06-14 00:50:07

标签: java android kotlin android-networking

我有4个API URL端点,在活动显示的主要活动中,我将同时向每个端点发出4个请求。如果所有这4个请求都成功完成,或者其中一个请求代码为4xx或5xx失败,则我想使我的请求指示器(进度条)消失。

因此,基本上我想在所有请求完成或其中一个失败之后执行一些操作?

在iOS开发中,我可以轻松地使用DispatchGroup来对某些动作进行分组,并在某些情况下执行某些操作。在Android中解决此问题的常用方法是什么?

这是我使用的代码,为简化起见,假设我有2种向服务器发出请求的方法。我正在使用改造:

首先,要获得产品:

fun getProductsFromServer(customerID: String, type: String = "", categoryID: String = "" , completion: (errorMessage: String?, products: ArrayList<Product>?) -> Unit) {

            val lakuinAPI = RetrofitHandler.getInstance(LakuinAPI::class.java)
            val call = lakuinAPI.getProductData("1","0","0","100000000000",type = type,customer_id = customerID,categories_id = categoryID)

            call.enqueue(object: Callback<ProductData> {

                override fun onFailure(call: Call<ProductData>, t: Throwable) {
                    completion("Failed to make netwroking call : ${t.localizedMessage}", null)
                }

                override fun onResponse(call: Call<ProductData>, response: Response<ProductData>) {

                    val productList = ArrayList<Product>()

                    if (!response.isSuccessful) {
                        completion("Error: ${response.code()}",productList)
                        return
                    }

                    val jsonProductData = response.body() ?: return
                    val statusSuccess = jsonProductData.success

                    if (statusSuccess == "1") {

                        val products = jsonProductData.product_data
                        completion(null,products)

                    } else if (statusSuccess == "0") {

                        val errorMessageFromServer = jsonProductData.message
                        completion(errorMessageFromServer,productList)


                    }


                }


            })
        }

第二次,获得横幅

fun getBannersFromServer(completion: (errorMessage: String?, banners: ArrayList<Banner>?) -> Unit) {

            val lakuinAPI = RetrofitHandler.getInstance(LakuinAPI::class.java)
            val call = lakuinAPI.getBanners()

            call.enqueue(object : Callback<BannerData> {

                override fun onFailure(call: Call<BannerData>, t: Throwable) {
                    completion("Failed to make netwroking call : ${t.localizedMessage}", null)
                }

                override fun onResponse(call: Call<BannerData>, response: Response<BannerData>) {

                    val bannerList = ArrayList<Banner>()

                    if (!response.isSuccessful()) {
                        completion("Error: ${response.code()}",bannerList)
                        return
                    }

                    val jsonBannerData = response.body() ?: return
                    val statusSuccess = jsonBannerData.success

                    if (statusSuccess == "1") {

                        val banners = jsonBannerData.data
                        completion(null,banners)

                    } else if (statusSuccess == "0") {
                        val errorMessageFromServer = jsonBannerData.message
                        completion(errorMessageFromServer,bannerList)


                    }

                }


            })




        }

然后这两个方法将在Main Activity中使用

private fun getProducts(type: String) {

        Product.getProductsFromServer(customerID = userData.id.toString(), type = type) { errorMessage, products ->

            errorMessage?.let {
                activity?.toast(it)
            } ?: run {

                val productList = products ?: ArrayList()
                setUpRecyclerView(type = type,products = productList)

            }


        }

    }


    private fun getBanners() {


        Banner.getBannersFromServer { errorMessage, banners ->

            errorMessage?.let {
                activity?.toast(it)
            } ?: run {
                val bannerList = banners ?: ArrayList()
                setUpImageSlideShow(banners = bannerList)
            }


        }
    }

所以,在调用getBanners()getProducts()之后,当这两个请求成功时,我想隐藏进度栏。如果失败,说我想做吐司按摩?该怎么做?

java没问题

3 个答案:

答案 0 :(得分:1)

要实现此目标,如果您将Kotlin用于Android开发,则首选使用Anko

doAsync {
    // ...
}

您也可以使用AsyncTask实现相同的功能,而且它是Android API,而不是JavaKotlin的语言功能。像这样使用AsyncTask

class someTask() : AsyncTask<Void, Void, String>() {
    override fun doInBackground(vararg params: Void?): String? {
        // ...
    }

    override fun onPreExecute() {
        super.onPreExecute()
        // ...
    }

    override fun onProgressUpdate(vararg text: String?) {
        super.onPostExecute(result)
        // ...
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)
        // ...
    }
}

请遵循此link,以查看任务在执行异步任务时如何响应。

答案 1 :(得分:1)

您可以使用翻新和协同程序轻松实现这一目标。

第1步创建改造呼叫

interface MyApi{

    @GET("end-point}")
    suspend fun firstCall(): Response<YourModelClassForResponse>

    @GET("end-point}")
    fun secondCall(): Response<YourModelClassForResponse>

    @GET("end-point}")
    fun thirdCall(): Response<YourModelClassForResponse>

    @GET("end-point}")
    fun fourthCall(): Call<YourModelClassForResponse>


    companion object {
        private const val BASE_URL = "bas url"
        operator fun invoke(): SmartFarmApi {
            return Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(BASE_URL)
                .build().create(MyApi::class.java)
        }
    }
}

步骤2使用协程调用您的API

    GlobalScope.launch { 
      val firstCall =  MyApi().firstCall()
      val secondCall=  MyApi().secondCall()
      val thirdCall=  MyApi().thirdCall()
      val fourthCall =  MyApi().fourthCall()
    }

尽管使用GlobalScope并不是一个好主意,但是为了使它变得快速,我在这里编写了它,您可以创建协程范围来进行这些调用。 我认为在单个活动或片段中并行调用4个不同的API并不是一个好主意。我认为您应该更改API并一次调用即可完成所有操作。

希望这会有所帮助。谢谢

答案 2 :(得分:0)

我不熟悉Retrofit,但这应该可以工作:

创建一个可公开访问的数组;每个请求完成或失败后,将状态添加到该数组;

override fun onFailure(call: Call<BannerData>, t: Throwable) {
                completion("Failed to make netwroking call : ${t.localizedMessage}", null)
                the_public_array.add("failure");
}
override fun onResponse(call: Call<BannerData>, response: Response<BannerData>) {
                val bannerList = ArrayList<Banner>()
                if (!response.isSuccessful()) {
                    the_public_array.add("failure")
                    completion("Error: ${response.code()}",bannerList)
                    return
                }
                val jsonBannerData = response.body() ?: return
                val statusSuccess = jsonBannerData.success
                if (statusSuccess == "1") {
                    the_public_array.add("success")
                    val banners = jsonBannerData.data
                    completion(null,banners)
                } else if (statusSuccess == "0") {
                    the_public_array.add("failure")
                    val errorMessageFromServer = jsonBannerData.message
                    completion(errorMessageFromServer,bannerList)
                }

            }

创建一个线程(在您的活动中),该线程运行代码,一直检查该数组,直到该数组包含一个失败的连接或四个成功的连接;然后在满足此条件的情况下(在ui线程中)将视图的可见性设置为“消失”;

Thread(Runnable {
    while(true){
        if(the_public_array.contains_four_success_status()||
                the_public_array.contains_one_failure_status()){
            this@MainActivity.runOnUiThread(java.lang.Runnable { 
                the_progress_bar.set_Visibility(Gone) 
            }) 
            break;
         }
    }
}).start();