diff options
Diffstat (limited to 'core/src/main/java/com/android/volley/toolbox/RequestFuture.java')
-rw-r--r-- | core/src/main/java/com/android/volley/toolbox/RequestFuture.java | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/core/src/main/java/com/android/volley/toolbox/RequestFuture.java b/core/src/main/java/com/android/volley/toolbox/RequestFuture.java new file mode 100644 index 0000000..f9cbce2 --- /dev/null +++ b/core/src/main/java/com/android/volley/toolbox/RequestFuture.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import android.os.SystemClock; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * A Future that represents a Volley request. + * + * <p>Used by providing as your response and error listeners. For example: + * + * <pre> + * RequestFuture<JSONObject> future = RequestFuture.newFuture(); + * MyRequest request = new MyRequest(URL, future, future); + * + * // If you want to be able to cancel the request: + * future.setRequest(requestQueue.add(request)); + * + * // Otherwise: + * requestQueue.add(request); + * + * try { + * JSONObject response = future.get(); + * // do something with response + * } catch (InterruptedException e) { + * // handle the error + * } catch (ExecutionException e) { + * // handle the error + * } + * </pre> + * + * @param <T> The type of parsed response this future expects. + */ +public class RequestFuture<T> implements Future<T>, Response.Listener<T>, Response.ErrorListener { + private Request<?> mRequest; + private boolean mResultReceived = false; + private T mResult; + private VolleyError mException; + + public static <E> RequestFuture<E> newFuture() { + return new RequestFuture<>(); + } + + private RequestFuture() {} + + public void setRequest(Request<?> request) { + mRequest = request; + } + + @Override + public synchronized boolean cancel(boolean mayInterruptIfRunning) { + if (mRequest == null) { + return false; + } + + if (!isDone()) { + mRequest.cancel(); + return true; + } else { + return false; + } + } + + @Override + public T get() throws InterruptedException, ExecutionException { + try { + return doGet(/* timeoutMs= */ null); + } catch (TimeoutException e) { + throw new AssertionError(e); + } + } + + @Override + public T get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + return doGet(TimeUnit.MILLISECONDS.convert(timeout, unit)); + } + + private synchronized T doGet(Long timeoutMs) + throws InterruptedException, ExecutionException, TimeoutException { + if (mException != null) { + throw new ExecutionException(mException); + } + + if (mResultReceived) { + return mResult; + } + + if (timeoutMs == null) { + while (!isDone()) { + wait(0); + } + } else if (timeoutMs > 0) { + long nowMs = SystemClock.uptimeMillis(); + long deadlineMs = nowMs + timeoutMs; + while (!isDone() && nowMs < deadlineMs) { + wait(deadlineMs - nowMs); + nowMs = SystemClock.uptimeMillis(); + } + } + + 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(); + } +} |