5

I'm experiencing a problem when using the RequestFuture class of volley. Actually it just stops at wait(0); inside the doGet() Function in the RequestFuture class below and is never getting woken up by onResponse or onErrorResponse as I think it should.

private synchronized T doGet(Long timeoutMs)
        throws InterruptedException, ExecutionException, TimeoutException {
    if (mException != null) {
        throw new ExecutionException(mException);
    }

    if (mResultReceived) {
        return mResult;
    }

    if (timeoutMs == null) {
        wait(0);
    } else if (timeoutMs > 0) {
        wait(timeoutMs);
    }

    if (mException != null) {
        throw new ExecutionException(mException);
    }

    if (!mResultReceived) {
        throw new TimeoutException();
    }

    return mResult;
}

@Override
public boolean isCancelled() {
    if (mRequest == null) {
        return false;
    }
    return mRequest.isCanceled();
}

@Override
public synchronized boolean isDone() {
    return mResultReceived || mException != null || isCancelled();
}

@Override
public synchronized void onResponse(T response) {
    mResultReceived = true;
    mResult = response;
    notifyAll();
}

@Override
public synchronized void onErrorResponse(VolleyError error) {
    mException = error;
    notifyAll();
}

This is the way i try to call all this above.

    RequestFuture<JSONObject> future = RequestFuture.newFuture();
    JsonObjectRequest myReq = new JsonObjectRequest(Request.Method.POST, url, jsonObj, future, future);
    requestQueue.add(myReq);

    try {

        JSONObject response = future.get();
    } catch (InterruptedException e) {
        // handle the error
    } catch (ExecutionException e) {
        // handle the error
    }

I also tried replacing the line

requestQueue.add(myReq);

with

future.setRequest(requestQueue.add(myReq));

or

future.setRequest(myReq);

which didn't help either.

I already tried a usual Volley Request which worked just fine using this parameters, so that shouldn't be the cause. I guess the problem is, that the request is never actually executed, which is why the response listeners are never reached. Also tried requestQueue.start(), but didn't change a thing.

I hope I explained my problem well enough, Thanks in advance!

Chintan Rathod
  • 25,864
  • 13
  • 83
  • 93
user2700475
  • 827
  • 2
  • 7
  • 16
  • Why are you trying to use RequestFuture? Can you share your use cases? – bogdan Sep 13 '13 at 06:25
  • Well problem I was facing is that i have three requests and the last of these three relies on the response of the first two requests. I already tried using different RequestQueues, but it always built all requests before starting them actually. So I never got to store the values of the first two so I could use them in the last request. My workaround at the moment is using custom event listeners to react on the responses of each request and start a new one once the one before is finished. – user2700475 Sep 13 '13 at 09:56
  • But you already have 2 listeners for your Volley requests: the success listener and the error listener. You can fetch you result(s) in the success listener (and maybe set some custom value in your error listeners - depending on your needs) and just launch your subsequent requests from there - the success and/or error listeners. This way, your requests are synchronous and you don't have to bother implementing RequestFuture. – bogdan Sep 13 '13 at 12:04
  • okay, I'll use them. I just thought using RequestFuture would be the better/cleaner approach, but it's not working properly as it seems. Thanks a lot! – user2700475 Sep 16 '13 at 10:02
  • 1
    I wish someone had been able to answer this. I'm having the same issue. Sigh. – nachoburton Oct 12 '13 at 01:35
  • 1
    See [@Blundell's answer to a similar question](http://stackoverflow.com/a/23808857/1518546). – John Cummings Oct 18 '14 at 18:13

4 Answers4

6

Adding a timeout to the get method will give the ability to catch the error, if no timeout is given then it sends the error back to the main thread. So changing JSONObject response = future.get(); with JSONObject response = future.get(REQUEST_TIMEOUT, TimeUnit.SECONDS); should do the trick and wrap it in a try catch for the timeout

Blair
  • 61
  • 1
  • 2
3

Solved!

JSONObject response = future.get();

Always run Future Request in seperate thread. It will not work in main thread. I am running Future Request Call in an IntentService and its working perfectly fine.

Happy Coding :)

Farhan
  • 3,162
  • 3
  • 25
  • 17
0

You need to call future.get() in another thread. Try wrapping it in an AsyncTask.

Looking at the source, it looks like RequestQueue kicks off a long chain of calls to load the response and which eventually end in RequestFuture.onResponse (which in turn calls notifyAll to notify the thread to stop waiting, as you mentioned). I think the problem is that wait(0) and the RequestQueue chain both run in the UI thread, so when wait(0) is called, the RequestQueue chain also waits, so onResponse never gets called, which is why that line just hangs (because wait(0) waits forever).

Patricia Li
  • 1,346
  • 10
  • 19
0

In addition to Blair's and Farhan's solutions, attaching a retry policy to the request also does the job.

request.setRetryPolicy(new DefaultRetryPolicy(RETRY_TIME, RETRY_ATTEMPTS, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));