背景 :因此,我有一个很大的项目,具有很多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.
更多推荐
将回调地狱转换为延迟对象
发布评论