将回调地狱转换为延迟对象 [英] Convert callback hell to deferred object

查看:64
本文介绍了将回调地狱转换为延迟对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景 :因此,我有一个很大的项目,具有很多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(...);
        }
    });
}

ApiCallbackApiResponse看起来像这样:

public interface ApiCallback<T> {
    void onResult(T response);
}

public class ApiResponse<T> {
    private T mResult;
    private ServiceError mError;
    ...
}

因此,在所有这些之前,我还使用了ApiClient.javaApiClient.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆