我有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没问题
答案 0 :(得分:1)
要实现此目标,如果您将Kotlin
用于Android开发,则首选使用Anko。
doAsync {
// ...
}
您也可以使用AsyncTask实现相同的功能,而且它是Android API
,而不是Java
或Kotlin
的语言功能。像这样使用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)
您可以使用翻新和协同程序轻松实现这一目标。
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)
}
}
}
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();