blob: 76e3c656072d48c8fff4e58af48054a1b8959090 [file] [log] [blame]
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -08001/*
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
17package com.android.volley;
18
Jean-Baptiste Queru6772bce2012-11-07 07:51:33 -080019import android.os.Process;
20
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080021import java.util.concurrent.BlockingQueue;
22
23/**
24 * Provides a thread for performing network dispatch from a queue of requests.
25 *
26 * Requests added to the specified queue are processed from the network via a
27 * specified {@link Network} interface. Responses are committed to cache, if
28 * eligible, using a specified {@link Cache} interface. Valid responses and
29 * errors are posted back to the caller via a {@link ResponseDelivery}.
30 */
31@SuppressWarnings("rawtypes")
32public class NetworkDispatcher extends Thread {
33 /** The queue of requests to service. */
34 private final BlockingQueue<Request> mQueue;
35 /** The network interface for processing requests. */
36 private final Network mNetwork;
37 /** The cache to write to. */
38 private final Cache mCache;
39 /** For posting responses and errors. */
40 private final ResponseDelivery mDelivery;
41 /** Used for telling us to die. */
42 private volatile boolean mQuit = false;
43
44 /**
45 * Creates a new network dispatcher thread. You must call {@link #start()}
46 * in order to begin processing.
47 *
48 * @param queue Queue of incoming requests for triage
49 * @param network Network interface to use for performing requests
50 * @param cache Cache interface to use for writing responses to cache
51 * @param delivery Delivery interface to use for posting responses
52 */
53 public NetworkDispatcher(BlockingQueue<Request> queue,
54 Network network, Cache cache,
55 ResponseDelivery delivery) {
56 mQueue = queue;
57 mNetwork = network;
58 mCache = cache;
59 mDelivery = delivery;
60 }
61
62 /**
63 * Forces this dispatcher to quit immediately. If any requests are still in
64 * the queue, they are not guaranteed to be processed.
65 */
66 public void quit() {
67 mQuit = true;
68 interrupt();
69 }
70
71 @Override
72 public void run() {
Jean-Baptiste Queru6772bce2012-11-07 07:51:33 -080073 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080074 Request request;
75 while (true) {
76 try {
77 // Take a request from the queue.
78 request = mQueue.take();
79 } catch (InterruptedException e) {
80 // We may have been interrupted because it was time to quit.
81 if (mQuit) {
82 return;
83 }
84 continue;
85 }
86
87 try {
88 request.addMarker("network-queue-take");
89
90 // If the request was cancelled already, do not perform the
91 // network request.
92 if (request.isCanceled()) {
93 request.finish("network-discard-cancelled");
94 continue;
95 }
96
97 // Perform the network request.
98 NetworkResponse networkResponse = mNetwork.performRequest(request);
99 request.addMarker("network-http-complete");
100
101 // If the server returned 304 AND we delivered a response already,
102 // we're done -- don't deliver a second identical response.
103 if (networkResponse.notModified && request.hasHadResponseDelivered()) {
104 request.finish("not-modified");
105 continue;
106 }
107
108 // Parse the response here on the worker thread.
109 Response<?> response = request.parseNetworkResponse(networkResponse);
110 request.addMarker("network-parse-complete");
111
112 // Write to cache if applicable.
113 // TODO: Only update cache metadata instead of entire record for 304s.
114 if (request.shouldCache() && response.cacheEntry != null) {
115 mCache.put(request.getCacheKey(), response.cacheEntry);
116 request.addMarker("network-cache-written");
117 }
118
119 // Post the response back.
120 request.markDelivered();
121 mDelivery.postResponse(request, response);
122 } catch (VolleyError volleyError) {
123 parseAndDeliverNetworkError(request, volleyError);
124 } catch (Exception e) {
125 VolleyLog.e("Unhandled exception %s", e.toString());
126 mDelivery.postError(request, new VolleyError(e));
127 }
128 }
129 }
130
131 private void parseAndDeliverNetworkError(Request<?> request, VolleyError error) {
132 error = request.parseNetworkError(error);
133 mDelivery.postError(request, error);
134 }
135}