Home | History | Annotate | Download | only in volley
      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;
     18 
     19 import android.os.Handler;
     20 
     21 import java.util.concurrent.Executor;
     22 
     23 /**
     24  * Delivers responses and errors.
     25  */
     26 public class ExecutorDelivery implements ResponseDelivery {
     27     /** Used for posting responses, typically to the main thread. */
     28     private final Executor mResponsePoster;
     29 
     30     /**
     31      * Creates a new response delivery interface.
     32      * @param handler {@link Handler} to post responses on
     33      */
     34     public ExecutorDelivery(final Handler handler) {
     35         // Make an Executor that just wraps the handler.
     36         mResponsePoster = new Executor() {
     37             @Override
     38             public void execute(Runnable command) {
     39                 handler.post(command);
     40             }
     41         };
     42     }
     43 
     44     /**
     45      * Creates a new response delivery interface, mockable version
     46      * for testing.
     47      * @param executor For running delivery tasks
     48      */
     49     public ExecutorDelivery(Executor executor) {
     50         mResponsePoster = executor;
     51     }
     52 
     53     @Override
     54     public void postResponse(Request<?> request, Response<?> response) {
     55         postResponse(request, response, null);
     56     }
     57 
     58     @Override
     59     public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
     60         request.markDelivered();
     61         request.addMarker("post-response");
     62         mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
     63     }
     64 
     65     @Override
     66     public void postError(Request<?> request, VolleyError error) {
     67         request.addMarker("post-error");
     68         Response<?> response = Response.error(error);
     69         mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null));
     70     }
     71 
     72     /**
     73      * A Runnable used for delivering network responses to a listener on the
     74      * main thread.
     75      */
     76     @SuppressWarnings("rawtypes")
     77     private class ResponseDeliveryRunnable implements Runnable {
     78         private final Request mRequest;
     79         private final Response mResponse;
     80         private final Runnable mRunnable;
     81 
     82         public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
     83             mRequest = request;
     84             mResponse = response;
     85             mRunnable = runnable;
     86         }
     87 
     88         @SuppressWarnings("unchecked")
     89         @Override
     90         public void run() {
     91             // NOTE: If cancel() is called off the thread that we're currently running in (by
     92             // default, the main thread), we cannot guarantee that deliverResponse()/deliverError()
     93             // won't be called, since it may be canceled after we check isCanceled() but before we
     94             // deliver the response. Apps concerned about this guarantee must either call cancel()
     95             // from the same thread or implement their own guarantee about not invoking their
     96             // listener after cancel() has been called.
     97 
     98             // If this request has canceled, finish it and don't deliver.
     99             if (mRequest.isCanceled()) {
    100                 mRequest.finish("canceled-at-delivery");
    101                 return;
    102             }
    103 
    104             // Deliver a normal response or error, depending.
    105             if (mResponse.isSuccess()) {
    106                 mRequest.deliverResponse(mResponse.result);
    107             } else {
    108                 mRequest.deliverError(mResponse.error);
    109             }
    110 
    111             // If this is an intermediate response, add a marker, otherwise we're done
    112             // and the request can be finished.
    113             if (mResponse.intermediate) {
    114                 mRequest.addMarker("intermediate-response");
    115             } else {
    116                 mRequest.finish("done");
    117             }
    118 
    119             // If we have been provided a post-delivery runnable, run it.
    120             if (mRunnable != null) {
    121                 mRunnable.run();
    122             }
    123        }
    124     }
    125 }
    126