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<JSONObject> 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