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 /** Requests with a sequence number below this one will have responses dropped. */ 31 private int mDiscardBefore = 0; 32 33 /** 34 * Creates a new response delivery interface. 35 * @param handler {@link Handler} to post responses on 36 */ ExecutorDelivery(final Handler handler)37 public ExecutorDelivery(final Handler handler) { 38 // Make an Executor that just wraps the handler. 39 mResponsePoster = new Executor() { 40 @Override 41 public void execute(Runnable command) { 42 handler.post(command); 43 } 44 }; 45 } 46 47 /** 48 * Creates a new response delivery interface, mockable version 49 * for testing. 50 * @param executor For running delivery tasks 51 */ ExecutorDelivery(Executor executor)52 public ExecutorDelivery(Executor executor) { 53 mResponsePoster = executor; 54 } 55 56 @Override postResponse(Request<?> request, Response<?> response)57 public void postResponse(Request<?> request, Response<?> response) { 58 postResponse(request, response, null); 59 } 60 61 @Override postResponse(Request<?> request, Response<?> response, Runnable runnable)62 public void postResponse(Request<?> request, Response<?> response, Runnable runnable) { 63 request.markDelivered(); 64 request.addMarker("post-response"); 65 mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); 66 } 67 68 @Override postError(Request<?> request, VolleyError error)69 public void postError(Request<?> request, VolleyError error) { 70 request.addMarker("post-error"); 71 Response<?> response = Response.error(error); 72 mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null)); 73 } 74 75 @Override discardBefore(int sequence)76 public void discardBefore(int sequence) { 77 mDiscardBefore = sequence; 78 } 79 80 /** 81 * A Runnable used for delivering network responses to a listener on the 82 * main thread. 83 */ 84 @SuppressWarnings("rawtypes") 85 private class ResponseDeliveryRunnable implements Runnable { 86 private final Request mRequest; 87 private final Response mResponse; 88 private final Runnable mRunnable; 89 ResponseDeliveryRunnable(Request request, Response response, Runnable runnable)90 public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) { 91 mRequest = request; 92 mResponse = response; 93 mRunnable = runnable; 94 } 95 96 @SuppressWarnings("unchecked") 97 @Override run()98 public void run() { 99 // Don't deliver the response if this request was canceled during processing 100 // or if discardBefore() has been called with a sequence number greater than 101 // or equal to this request's sequence number. 102 boolean drained = mRequest.isDrainable() && 103 (mRequest.getSequence() < mDiscardBefore); 104 105 // If this request has been drained or canceled, finish it and don't deliver. 106 if (drained || mRequest.isCanceled()) { 107 mRequest.finish("canceled-at-delivery"); 108 return; 109 } 110 111 // Deliver a normal response or error, depending. 112 if (mResponse.isSuccess()) { 113 mRequest.deliverResponse(mResponse.result); 114 } else { 115 mRequest.deliverError(mResponse.error); 116 } 117 118 // If this is an intermediate response, add a marker, otherwise we're done 119 // and the request can be finished. 120 if (mResponse.intermediate) { 121 mRequest.addMarker("intermediate-response"); 122 } else { 123 mRequest.finish("done"); 124 } 125 126 // If we have been provided a post-delivery runnable, run it. 127 if (mRunnable != null) { 128 mRunnable.run(); 129 } 130 } 131 } 132 } 133