aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/android/volley/toolbox/AsyncHttpStack.java')
-rw-r--r--src/main/java/com/android/volley/toolbox/AsyncHttpStack.java170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java b/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
new file mode 100644
index 0000000..bafab8c
--- /dev/null
+++ b/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2020 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 androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import com.android.volley.AuthFailureError;
+import com.android.volley.Request;
+import com.android.volley.VolleyLog;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
+
+/** Asynchronous extension of the {@link BaseHttpStack} class. */
+public abstract class AsyncHttpStack extends BaseHttpStack {
+ private ExecutorService mBlockingExecutor;
+ private ExecutorService mNonBlockingExecutor;
+
+ public interface OnRequestComplete {
+ /** Invoked when the stack successfully completes a request. */
+ void onSuccess(HttpResponse httpResponse);
+
+ /** Invoked when the stack throws an {@link AuthFailureError} during a request. */
+ void onAuthError(AuthFailureError authFailureError);
+
+ /** Invoked when the stack throws an {@link IOException} during a request. */
+ void onError(IOException ioException);
+ }
+
+ /**
+ * Makes an HTTP request with the given parameters, and calls the {@link OnRequestComplete}
+ * callback, with either the {@link HttpResponse} or error that was thrown.
+ *
+ * @param request to perform
+ * @param additionalHeaders to be sent together with {@link Request#getHeaders()}
+ * @param callback to be called after retrieving the {@link HttpResponse} or throwing an error.
+ */
+ public abstract void executeRequest(
+ Request<?> request, Map<String, String> additionalHeaders, OnRequestComplete callback);
+
+ /**
+ * This method sets the non blocking executor to be used by the stack for non-blocking tasks.
+ * This method must be called before executing any requests.
+ */
+ @RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
+ public void setNonBlockingExecutor(ExecutorService executor) {
+ mNonBlockingExecutor = executor;
+ }
+
+ /**
+ * This method sets the blocking executor to be used by the stack for potentially blocking
+ * tasks. This method must be called before executing any requests.
+ */
+ @RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
+ public void setBlockingExecutor(ExecutorService executor) {
+ mBlockingExecutor = executor;
+ }
+
+ /** Gets blocking executor to perform any potentially blocking tasks. */
+ protected ExecutorService getBlockingExecutor() {
+ return mBlockingExecutor;
+ }
+
+ /** Gets non-blocking executor to perform any non-blocking tasks. */
+ protected ExecutorService getNonBlockingExecutor() {
+ return mNonBlockingExecutor;
+ }
+
+ /**
+ * Performs an HTTP request with the given parameters.
+ *
+ * @param request the request to perform
+ * @param additionalHeaders additional headers to be sent together with {@link
+ * Request#getHeaders()}
+ * @return the {@link HttpResponse}
+ * @throws IOException if an I/O error occurs during the request
+ * @throws AuthFailureError if an authentication failure occurs during the request
+ */
+ @Override
+ public final HttpResponse executeRequest(
+ Request<?> request, Map<String, String> additionalHeaders)
+ throws IOException, AuthFailureError {
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicReference<Response> entry = new AtomicReference<>();
+ executeRequest(
+ request,
+ additionalHeaders,
+ new OnRequestComplete() {
+ @Override
+ public void onSuccess(HttpResponse httpResponse) {
+ Response response =
+ new Response(
+ httpResponse,
+ /* ioException= */ null,
+ /* authFailureError= */ null);
+ entry.set(response);
+ latch.countDown();
+ }
+
+ @Override
+ public void onAuthError(AuthFailureError authFailureError) {
+ Response response =
+ new Response(
+ /* httpResponse= */ null,
+ /* ioException= */ null,
+ authFailureError);
+ entry.set(response);
+ latch.countDown();
+ }
+
+ @Override
+ public void onError(IOException ioException) {
+ Response response =
+ new Response(
+ /* httpResponse= */ null,
+ ioException,
+ /* authFailureError= */ null);
+ entry.set(response);
+ latch.countDown();
+ }
+ });
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ VolleyLog.e(e, "while waiting for CountDownLatch");
+ Thread.currentThread().interrupt();
+ throw new InterruptedIOException(e.toString());
+ }
+ Response response = entry.get();
+ if (response.httpResponse != null) {
+ return response.httpResponse;
+ } else if (response.ioException != null) {
+ throw response.ioException;
+ } else {
+ throw response.authFailureError;
+ }
+ }
+
+ private static class Response {
+ HttpResponse httpResponse;
+ IOException ioException;
+ AuthFailureError authFailureError;
+
+ private Response(
+ @Nullable HttpResponse httpResponse,
+ @Nullable IOException ioException,
+ @Nullable AuthFailureError authFailureError) {
+ this.httpResponse = httpResponse;
+ this.ioException = ioException;
+ this.authFailureError = authFailureError;
+ }
+ }
+}