将回调地狱转换为延迟对象

2024-04-19

背景:所以,我有一个相当大的项目,有很多 API 函数。我正在考虑完全转向协程,但由于它们的实现方式是Callback并不是Deferred,我无法有效地使用它们。例如:我想做apiCallOne(), apiCallTwo() and apiCallThree()异步和调用.await()等到最后一个请求完成后再更改 UI。

现在该项目的结构如下:

最底部(或顶部)是ApiService.java:

interface ApiService {
    @GET("...")
    Call<Object> getData();
    ...
}

然后我有一个ClientBase.java: 功能createRequest()是解析改造响应的主要功能。

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 and ApiResponse看起来像这样:

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

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

所以,在这一切之前,我也ApiClient.java它使用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物体? (我愿意为此创建另一个包装类)


所以一般来说,一个简单的方法是返回一个suspendCancellableCoroutine来自挂起函数,然后您可以异步完成该函数。所以在你的情况下,你可能会写这样的内容:

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)如果你想通过异常处理来处理错误。

那是说:

由于您正在使用 Retrofit,我建议仅添加Retrofit2-kotlin-协程-适配器 https://github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter依赖项本身就为您添加了这种支持。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将回调地狱转换为延迟对象 的相关文章

随机推荐