Home | History | Annotate | Download | only in toolbox
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.volley.toolbox;
     18 
     19 import com.android.volley.Request;
     20 import com.android.volley.Response;
     21 import com.android.volley.VolleyError;
     22 
     23 import java.util.concurrent.ExecutionException;
     24 import java.util.concurrent.Future;
     25 import java.util.concurrent.TimeUnit;
     26 import java.util.concurrent.TimeoutException;
     27 
     28 /**
     29  * A Future that represents a Volley request.
     30  *
     31  * Used by providing as your response and error listeners. For example:
     32  * <pre>
     33  * RequestFuture&lt;JSONObject&gt; future = RequestFuture.newFuture();
     34  * MyRequest request = new MyRequest(URL, future, future);
     35  *
     36  * // If you want to be able to cancel the request:
     37  * future.setRequest(requestQueue.add(request));
     38  *
     39  * // Otherwise:
     40  * requestQueue.add(request);
     41  *
     42  * try {
     43  *   JSONObject response = future.get();
     44  *   // do something with response
     45  * } catch (InterruptedException e) {
     46  *   // handle the error
     47  * } catch (ExecutionException e) {
     48  *   // handle the error
     49  * }
     50  * </pre>
     51  *
     52  * @param <T> The type of parsed response this future expects.
     53  */
     54 public class RequestFuture<T> implements Future<T>, Response.Listener<T>,
     55        Response.ErrorListener {
     56     private Request<?> mRequest;
     57     private boolean mResultReceived = false;
     58     private T mResult;
     59     private VolleyError mException;
     60 
     61     public static <E> RequestFuture<E> newFuture() {
     62         return new RequestFuture<E>();
     63     }
     64 
     65     private RequestFuture() {}
     66 
     67     public void setRequest(Request<?> request) {
     68         mRequest = request;
     69     }
     70 
     71     @Override
     72     public synchronized boolean cancel(boolean mayInterruptIfRunning) {
     73         if (mRequest == null) {
     74             return false;
     75         }
     76 
     77         if (!isDone()) {
     78             mRequest.cancel();
     79             return true;
     80         } else {
     81             return false;
     82         }
     83     }
     84 
     85     @Override
     86     public T get() throws InterruptedException, ExecutionException {
     87         try {
     88             return doGet(null);
     89         } catch (TimeoutException e) {
     90             throw new AssertionError(e);
     91         }
     92     }
     93 
     94     @Override
     95     public T get(long timeout, TimeUnit unit)
     96             throws InterruptedException, ExecutionException, TimeoutException {
     97         return doGet(TimeUnit.MILLISECONDS.convert(timeout, unit));
     98     }
     99 
    100     private synchronized T doGet(Long timeoutMs)
    101             throws InterruptedException, ExecutionException, TimeoutException {
    102         if (mException != null) {
    103             throw new ExecutionException(mException);
    104         }
    105 
    106         if (mResultReceived) {
    107             return mResult;
    108         }
    109 
    110         if (timeoutMs == null) {
    111             wait(0);
    112         } else if (timeoutMs > 0) {
    113             wait(timeoutMs);
    114         }
    115 
    116         if (mException != null) {
    117             throw new ExecutionException(mException);
    118         }
    119 
    120         if (!mResultReceived) {
    121             throw new TimeoutException();
    122         }
    123 
    124         return mResult;
    125     }
    126 
    127     @Override
    128     public boolean isCancelled() {
    129         if (mRequest == null) {
    130             return false;
    131         }
    132         return mRequest.isCanceled();
    133     }
    134 
    135     @Override
    136     public synchronized boolean isDone() {
    137         return mResultReceived || mException != null || isCancelled();
    138     }
    139 
    140     @Override
    141     public synchronized void onResponse(T response) {
    142         mResultReceived = true;
    143         mResult = response;
    144         notifyAll();
    145     }
    146 
    147     @Override
    148     public synchronized void onErrorResponse(VolleyError error) {
    149         mException = error;
    150         notifyAll();
    151     }
    152 }
    153 
    154