Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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