简体   繁体   English

Java中的多个异步请求处理

[英]Multiple asynchronous request handling in java

I'm writing android app, which uses some site api. 我正在写android应用程序,它使用一些站点api。 This site provides sort of SDK to handle this api. 该站点提供了一些用于处理此api的SDK。 I'm using it to make some requests to the site. 我正在用它向网站提出一些要求。
So, to make a request I should do like this: 因此,要发出请求,我应该这样做:

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);

This listener runs asynchronously, so if I make single request, all goes fine: I can handle it inside onComplete method. listener异步运行,因此,如果我发出单个请求,一切都会很好:我可以在onComplete方法中处理它。 But what to do if I need to make multiple requests, furthermore, each next request depends on previous response? 但是,如果我需要发出多个请求,而且每个下一个请求都取决于先前的响应,该怎么办? I only see two ways, both look awful: 我只看到两种方法,两种方法看起来都很糟糕:
1. Make each next request in the onComplete method. 1. 使用onComplete方法发出每个下一个请求。 This seems to be too nesting and inflexible practice. 这似乎过于嵌套和不灵活。
2. Make some kind of synchronous operation: after main thread executes request, check somehow if onComplete executed (btw, how? with some kind of flag objects?) and if not, do Thread.sleep(1000) , repeat this until response returned, than make another response. 2.进行 某种同步操作:在主线程执行请求之后,以某种方式检查onComplete执行(btw,如何?使用某种标志对象?),否则,执行Thread.sleep(1000) ,重复此操作直到返回响应,而不是做出其他回应。
So, tell me please if there are 'normal' way to handle multiple async requests? 因此,请告诉我是否有“正常”方式来处理多个异步请求?

Multiple Async is really ugly in java, too much boilerplate. Java中的Multiple Async确实很难看,太多样板了。 Below is how you can hand-roll what you need. 以下是如何手动滚动所需内容的方法。 But I suggest researching a library as well. 但我建议也研究图书馆。

Solution for #1 #1解决方案

There's no nesting here (at least not very visible) if you explode your code well: You can even start in the middle of the chain if you already have the necessary data. 如果很好地分解了代码,这里就没有嵌套(至少不是很明显):如果已经有了必要的数据,甚至可以在链的中间开始。 Esentially you can make your own async interface(s) based on VK classes, but VK totally hidden. 基本上,您可以基于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);
    }
}

Solution for #2 #2解决方案

To make an async request sync you can do this: 要使异步请求同步,您可以执行以下操作:
ONLY ever do this on a background thread! 只能在后台线程上执行此操作! And also note that AsyncTask executes tasks 1 by 1 so if you put this in an AsyncTask it'll block other async tasks from executing! 还要注意, AsyncTask按1的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

See this about interrupts! 对中断!

You should give RxJava , a reactive extensions implementation in java a try. 您应该尝试使用Java中的反应性扩展RxJava实现。 It allows composition of asynchronous calls in a very simple way through observables. 它允许通过可观察对象以非常简单的方式来组成异步调用。 There's also an android extension, RxAndroid that gives you access to an android scheduler and activity or fragment lifecycle aware observables. 还有一个android扩展RxAndroid ,可让您访问android调度程序以及活动或片段生命周期感知的可观察对象。

There are few tutorials and write-ups about using Rx with android, but you should checkout out Dan Lew's one as it covers all the things you'll need. 关于在Android上使用Rx的教程和文章很少,但是您应该签出Dan Lew的教程和文章,因为它涵盖了您需要的所有东西。 Link here: Grokking RxJava 链接在这里: Grokking RxJava

I was thinking about simple solution a lot, and I've done this: 我很多时候都在考虑简单的解决方案,而我做到了:

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);        
}

So this request wrapper calls itself recursively until all requests handled, coherently and carefully... Hope this helps somebody. 因此,此请求包装程序将以递归方式调用自身,直到所有请求均连贯且谨慎地处理为止。希望这对某些人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM