Android中如何将Apollo异步回调封装为返回Intern对象的同步方法
Java中如何实现Apollo GraphQL异步调用的同步返回(类似async/await)?
我来帮你解决这个问题——你想要把Apollo的异步回调逻辑封装成能直接返回Intern对象的方法,类似async/await的效果对吧?在Java里确实没有像Kotlin或JavaScript那样原生的async/await语法,但有几种可行的方案可以实现你的需求,而且不需要提前创建对象再在回调里赋值:
方案1:用CompletableFuture包装异步回调,模拟await效果
Java 8及以上提供了CompletableFuture,可以把Apollo的回调式异步调用转换成Future,然后通过阻塞等待获取结果,这就类似async/await的效果了。
import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; public InternQuery.Intern getIntern() throws ExecutionException, InterruptedException { CompletableFuture<InternQuery.Intern> resultFuture = new CompletableFuture<>(); // 构建查询和ApolloCall InternQuery query = InternQuery.builder().build(); ApolloCall<InternQuery.Data> apolloCall = new HoraApolloClient(this.context).getHoraApolloClient().query(query); apolloCall.enqueue(new ApolloCall.Callback<InternQuery.Data>() { @Override public void onResponse(@Nonnull Response<InternQuery.Data> response) { try { InternQuery.Data rData = response.data(); // 这里保留你的错误处理逻辑 if (rData == null || rData.intern() == null) { resultFuture.completeExceptionally(new RuntimeException("Failed to get intern data")); return; } resultFuture.complete(rData.intern()); } catch (Exception e) { resultFuture.completeExceptionally(e); } } @Override public void onFailure(@Nonnull ApolloException e) { resultFuture.completeExceptionally(e); } }); // 阻塞当前线程,直到Future完成,类似await return resultFuture.get(); }
注意事项:
- 绝对不能在Android主线程调用这个方法!
resultFuture.get()会阻塞线程,主线程被阻塞会直接导致ANR(应用无响应)。你需要在后台线程执行,比如用ExecutorService、AsyncTask或者Android Jetpack的Coroutine(Java可以借助kotlinx-coroutines-java库)。 - 如果调用线程被中断,
get()会抛出InterruptedException,需要处理或向上抛出。
方案2:直接使用Apollo的同步执行方法
其实Apollo客户端本身就提供了同步执行的execute()方法,不需要自己包装Future,直接就能同步获取响应结果,这是更简单的方式:
public InternQuery.Intern getIntern() throws ApolloException { // 构建查询和ApolloCall InternQuery query = InternQuery.builder().build(); ApolloCall<InternQuery.Data> apolloCall = new HoraApolloClient(this.context).getHoraApolloClient().query(query); // 同步执行查询,直接获取响应 Response<InternQuery.Data> response = apolloCall.execute(); InternQuery.Data rData = response.data(); // 保留你的错误处理逻辑 if (rData == null || rData.intern() == null) { throw new RuntimeException("Failed to get intern data"); } return rData.intern(); }
注意事项:
- 和方案1一样,
execute()是阻塞式方法,必须在后台线程执行,不能在主线程调用。 - 执行过程中如果出现网络错误或GraphQL错误,会抛出
ApolloException,需要捕获或向上抛出。
额外说明:避免阻塞的替代方案
如果你不想阻塞线程,但又希望代码逻辑更简洁,也可以考虑使用RxJava结合Apollo的Rx扩展(apollo-rxjava3),用响应式流的方式处理异步结果,但这种方式不是直接返回Intern对象,而是返回Observable<InternQuery.Intern>,需要订阅处理结果。不过这和你想要的“直接返回对象”的需求不太一致,所以优先推荐上面两种方案。
内容的提问来源于stack exchange,提问作者yerassyl
相关产品推荐
相关产品推荐

