【问题标题】:Multiple asynchronous request handling in javajava中的多个异步请求处理
【发布时间】:2014-10-25 15:56:53
【问题描述】:

我正在编写使用一些站点 api 的 android 应用程序。这个站点提供了一种 SDK 来处理这个 api。我正在使用它向网站发出一些请求。
因此,要提出请求,我应该这样做:

VKRequestListener listener = new VKRequestListener(){
    @Override
    public void onComplete(VKResponse response){
      // do smth when response is complete
    }
}
VKRequest vkRequest = new VKRequest("request", "parameters");
vkRequest.executeWithListener(listener);

这个listener 异步运行,所以如果我发出一个请求,一切都会好起来的: 我可以在onComplete 方法中处理它。 但是如果我需要发出多个请求怎么办,此外,每个下一个请求都取决于先前的响应? 我只看到两种方法,看起来都很糟糕:
1. onComplete 方法中发出每个下一个请求。这似乎是一种过于嵌套和不灵活的做法。
2. 进行某种同步操作:在主线程执行请求后,以某种方式检查onComplete是否已执行(顺便说一句,怎么样?使用某种标志对象?)如果没有,请执行Thread.sleep(1000),重复此操作直到返回响应,然后再进行响应。
那么,请告诉我是否有“正常”的方式来处理多个异步请求?

【问题讨论】:

标签: java android multithreading asynchronous


【解决方案1】:

Multiple Async 在 java 中真的很丑,样板太多。以下是您如何手动滚动您需要的东西。但我建议也研究一下图书馆。

#1 的解决方案

如果你很好地分解你的代码,这里就没有嵌套(至少不是很明显): 如果您已经拥有必要的数据,您甚至可以从链的中间开始。 本质上,您可以基于 VK 类制作自己的异步接口,但 VK 完全隐藏。

class MyRequests {
    interface GetStuffResult {
        void done(String result, float result2);
        // you can even put other callbacks here to help make decisions in the chain
        // based on UI element states for example
    }

    static void startGetStuff1(String param1, String param2, final GetStuffResult result) {
        VKRequestListener listener = new VKRequestListener(){
            @Override
            public void onComplete(VKResponse response){
                // extract parameters for next request 
                String newParameter1 = ...;
                int newParameter2 = ...;
                startGetStuff2(newParameter1, newParameter2, result);
            }
        };
        VKRequest vkRequest = new VKRequest("request", buildParameters1(param1, param2));
        vkRequest.executeWithListener(listener);
    }

    static void startGetStuff2(String param1, int param2, final GetStuffResult result) {
        VKRequestListener listener = new VKRequestListener(){
            @Override
            public void onComplete(VKResponse response){
                // extract parameters for next request 
                startGetStuff3(newParameter1, newParameter2, newParameter3, result);
            }
        };
        VKRequest vkRequest = new VKRequest("request", buildParameters2(param1, param2));
        vkRequest.executeWithListener(listener);
    }

    static void startGetStuff3(String param1, int param2, Date param3, final GetStuffResult result) {
        VKRequestListener listener = new VKRequestListener() {
            @Override
            public void onComplete(VKResponse response) {
                // extract result
                result.done(resultingString, resultingFloat);
            }
        };
        VKRequest vkRequest = new VKRequest("request", buildParameters3(param1, param2, param3));
        vkRequest.executeWithListener(listener);
    }
}

#2 的解决方案

要进行异步请求同步,您可以这样做:
只能在后台线程上这样做! 还要注意AsyncTask 会一个接一个地执行任务,所以如果你把它放在AsyncTask 中,它会阻止其他异步任务的执行!

final AtomicReference<VKResponse> result = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
VKRequestListener listener = new VKRequestListener(){
    @Override
    public void onComplete(VKResponse response){
        result.set(response);
        latch.countDown();
    }
};
VKRequest vkRequest = new VKRequest("request", "parameters");
vkRequest.executeWithListener(listener);    
// call countDown() even if the request fails if you have an error callback as well!
// and check the existence of response/flag you set if it failed

try {
    latch.await();
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
VKResponse response = result.get(); // will be null if interrupted
// do smth when response is complete

请参阅this 了解中断!

【讨论】:

  • 所以,两种方法我都试过了,第一种太笨重,第二种不适合我(
  • 这是一些可选的提示,很好的建议我实现了这个。谢谢
  • 解决方案 #2 适用于 Interceptor 中的刷新令牌,非常感谢。
【解决方案2】:

您应该尝试一下RxJava,这是一个 java 中的反应式扩展实现。它允许通过 observables 以非常简单的方式组合异步调用。还有一个 android 扩展,RxAndroid,可让您访问 android 调度程序和活动或片段生命周期感知 observables。

关于在 android 中使用 Rx 的教程和文章很少,但您应该查看 Dan Lew 的教程和文章,因为它涵盖了您需要的所有内容。链接在这里:Grokking RxJava

【讨论】:

    【解决方案3】:

    我一直在考虑简单的解决方案,我已经这样做了:

    class RequestFlags{
        int requestCount;
        Params params;
    };
    private final RequestFlags requestFlags;
    
    public requestWrapper(RequestFlags rf){
        VKRequestListener listener = new VKRequestListener(){
            @Override
            public void onComplete(VKResponse response){
            // do smth when response is complete
                 if(requestFlags.requestCount != 0) {
                     requestFlags.requestCount--;
                     requestFlags.params = doSmth(response);
                     requestWrapper(requestFlags);
                 } else{
                     // we finished - do smth on finish
                 }
            }
        }
        Params someParams;
        switch(requestFlags.params){
            case param1: someParams = doSmthElse();
            break;
            case param2: someParams = null;
            break;
            // etc, etc...
        }
        VKRequest vkRequest = new VKRequest("request", someParams);
        vkRequest.executeWithListener(listener);        
    }
    

    所以这个请求包装器会递归地调用自己,直到所有请求都被连贯而仔细地处理...... 希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-27
      • 2019-03-26
      • 1970-01-01
      • 2015-02-22
      • 2018-06-12
      • 2019-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多