将回调地狱转换为延迟对象 [英] Convert callback hell to deferred object
问题描述
背景 :因此,我有一个很大的项目,具有很多API函数.我正在考虑完全使用协程,但是由于将它们实现为Callback
而不是Deferred
,因此我无法高效使用它们.例如:我想执行apiCallOne()
,apiCallTwo()
和apiCallThree()
异步并调用.await()
,直到最后一个请求完成,然后再更改UI.
Background: So, I have a pretty big project with a lot of API functions. I'm thinking of completely moving to coroutines, but as they are implemented as Callback
and not Deferred
, I can not use them efficiently. For instance: I would like to do apiCallOne()
, apiCallTwo()
and apiCallThree()
async and call .await()
to wait till the last request is completed before changing UI.
现在,项目的结构如下:
Now the project is structured like this:
最底端(或顶部)是ApiService.java
:
interface ApiService {
@GET("...")
Call<Object> getData();
...
}
然后我有一个ClientBase.java
:
函数createRequest()
是解析改造响应的主要函数.
Then I have a ClientBase.java
:
function createRequest()
is main function for parsing retrofit response.
void getUserName(String name, ApiCallback<ApiResponse<...>> callback) {
createRequest(ApiService.getData(...), new ApiCallback<ApiResponse<?>>() {
@Override
public void onResult(ServiceResponse response) {
callback.onResult(response);
}
});
}
private void createRequest(Call call, final ApiCallback<ApiResponse<?>> callback) {
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, retrofit2.Response response) {
//heavy parsing
}
// return request results wrapped into ApiResponse object
callback.onResult(new ApiResponse<>(...));
}
@Override
public void onFailure(Call call, Throwable t) {
// return request results wrapped into ApiResponse object
callback.onResult(...);
}
});
}
ApiCallback
和ApiResponse
看起来像这样:
public interface ApiCallback<T> {
void onResult(T response);
}
public class ApiResponse<T> {
private T mResult;
private ServiceError mError;
...
}
因此,在所有这些之前,我还使用了ApiClient.java
的ApiClient.java
:
So, before all of this, I have also ApiClient.java
which uses ClientBase.createRequest()
:
public void getUserName(String name, ApiCallback<ApiResponse<..>> callback) {
ClientBase.getUserName(secret, username, new ServiceCallback<ServiceResponse<RegistrationInvite>>() {
@Override
public void onResult(ServiceResponse<RegistrationInvite> response) {
...
callback.onResult(response);
}
});
}
如您所见,这非常非常糟糕.如何至少传输这些代码以确保ApiClient.java
函数返回Deferred
对象? (我愿意为此创建另一个包装器类)
As you can see, this is very, very bad. How can I transfer some of this code at least to make sure, that ApiClient.java
function return Deferred
objects? (I'm willing to create another wrapper class for this)
推荐答案
因此,通常,执行此操作的一种简单方法是从挂起函数返回suspendCancellableCoroutine
,然后可以异步完成该操作.因此,在您的情况下,您可能会编写类似以下内容的
So in general, a simple way to do this is to return a suspendCancellableCoroutine
from a suspending function, which you can then complete asynchronously. So in your case, you might write something like:
suspend fun getUserName(name: String): ApiResponse<...> {
return suspendCancellableCoroutine { continuation ->
createRequest(ApiService.getData(...), new ApiCallback<ApiResponse<...>>() {
@Override
public void onResult(ApiResponse<...> response) {
continuation.resume(response)
}
});
}
}
基本上,您返回等价于SettableFuture
的内容,然后在成功或失败时将其标记为完成.如果您想通过异常处理来处理错误,也有continueWithException(Throwable)
.
You basically return the equivalent of a SettableFuture
and then mark it complete when you get success or failure. There's also continueWithException(Throwable)
if you want to handle errors via exception handling.
说:
由于您使用的是Retrofit,因此建议您仅添加 retrofit2-kotlin -coroutines-adapter 依赖关系,从而在本机上为您添加了这种支持.
Since you're using Retrofit, I would recommend just adding in the retrofit2-kotlin-coroutines-adapter dependency which adds in this support for you natively.
这篇关于将回调地狱转换为延迟对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!