Volley源码解析

2023-05-16

概述

本文基于Volley 1.1.1版本的源码。

Volley是Google官方出的一套小而巧的异步请求库,该框架封装的扩展性很强,支持HttpClient、HttpUrlConnection,甚至支持OkHttp。Volley不适用于下载大量内容的操作或流式传输操作,因为在解析过程中,Volley会将所有响应存储在内存中,因此Volley不适合上传和下载大文件。

添加依赖:


1
  

implementation 'com.android.volley:volley:1.1.1'
  

使用:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  

RequestQueue queue = Volley.newRequestQueue(context);
String url ="http://www.google.com";

StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        // in UI Thread
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        // in UI Thread
    }
});
stringRequest.setTag(TAG);

// Add the request to the RequestQueue.
queue.add(stringRequest);

// onStop
queue.cancelAll(TAG);
  

创建请求队列

Volley类中有多个重载的newRequestQueue静态方法:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  

public class Volley {
    private static final String DEFAULT_CACHE_DIR = "volley";

    public static RequestQueue newRequestQueue(Context context) {
        return newRequestQueue(context, (BaseHttpStack) null);
    }

    public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
        BasicNetwork network;
        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                network = new BasicNetwork(new HurlStack());
            } else {
                // ...
            }
        } else {
            network = new BasicNetwork(stack);
        }

        return newRequestQueue(context, network);
    }

    private static RequestQueue newRequestQueue(Context context, Network network) {
        final Context appContext = context.getApplicationContext();
        DiskBasedCache.FileSupplier cacheSupplier =
                new DiskBasedCache.FileSupplier() {
                    private File cacheDir = null;

                    @Override
                    public File get() {
                        if (cacheDir == null) {
                            cacheDir = new File(appContext.getCacheDir(), DEFAULT_CACHE_DIR);
                        }
                        return cacheDir;
                    }
                };
        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheSupplier), network);
        queue.start();
        return queue;
    }
}
  

RequestQueue类构造方法如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  

public class RequestQueue {
    private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;
    private final Cache mCache;
    private final Network mNetwork;
    private final ResponseDelivery mDelivery;
    private final NetworkDispatcher[] mDispatchers;
    private CacheDispatcher mCacheDispatcher;

    public RequestQueue(
            Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
        mCache = cache;
        mNetwork = network;
        mDispatchers = new NetworkDispatcher[threadPoolSize];
        mDelivery = delivery;
    }

    public RequestQueue(Cache cache, Network network, int threadPoolSize) {
        this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper())));
    }

    public RequestQueue(Cache cache, Network network) {
        this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);
    }
}
  

RequestQueue#start()方法如下,可以看出就是启动了一个Cache Dispatcher和指定数目的Network Dispatcher:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  

/** Starts the dispatchers in this queue. */
public void start() {
    // Make sure any currently running dispatchers are stopped.
    stop();
    // Create the cache dispatcher and start it.
    mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
    mCacheDispatcher.start();

    // Create network dispatchers (and corresponding threads) up to the pool size.
    for (int i = 0; i < mDispatchers.length; i++) {
        NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
        mDispatchers[i] = networkDispatcher;
        networkDispatcher.start();
    }
}

/** Stops the cache and network dispatchers. */
public void stop() {
    if (mCacheDispatcher != null) {
        mCacheDispatcher.quit();
    }
    for (final NetworkDispatcher mDispatcher : mDispatchers) {
        if (mDispatcher != null) {
            mDispatcher.quit();
        }
    }
}
  

RequestQueue事件

在RequestQueue类中定义了一些事件:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  

public @interface RequestEvent {
    /** The request was added to the queue. */
    public static final int REQUEST_QUEUED = 0;
    /** Cache lookup started for the request. */
    public static final int REQUEST_CACHE_LOOKUP_STARTED = 1;
    /** Cache lookup finished for the request and cached response is delivered or request is queued for network dispatching. */
    public static final int REQUEST_CACHE_LOOKUP_FINISHED = 2;
    /** Network dispatch started for the request. */
    public static final int REQUEST_NETWORK_DISPATCH_STARTED = 3;
    /** The network dispatch finished for the request and response (if any) is delivered. */
    public static final int REQUEST_NETWORK_DISPATCH_FINISHED = 4;
    /** All the work associated with the request is finished and request is removed from all the queues. */
    public static final int REQUEST_FINISHED = 5;
}

public interface RequestEventListener {
    void onRequestEvent(Request<?> request, @RequestEvent int event);
}

private final List<RequestEventListener> mEventListeners = new ArrayList<>();
  

可以通过下面几个方法操作这些事件:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  

void sendRequestEvent(Request<?> request, @RequestEvent int event) {
    synchronized (mEventListeners) {
        for (RequestEventListener listener : mEventListeners) {
            listener.onRequestEvent(request, event);
        }
    }
}

public void addRequestEventListener(RequestEventListener listener) {
    synchronized (mEventListeners) {
        mEventListeners.add(listener);
    }
}

public void removeRequestEventListener(RequestEventListener listener) {
    synchronized (mEventListeners) {
        mEventListeners.remove(listener);
    }
}
  

发送请求

RequestQueue#add()方法如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  

private final AtomicInteger mSequenceGenerator = new AtomicInteger();
private final Set<Request<?>> mCurrentRequests = new HashSet<>();
private final PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<>();
private final PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<>();

public <T> Request<T> add(Request<T> request) {
    // Tag the request as belonging to this queue and add it to the set of current requests.
    request.setRequestQueue(this);
    synchronized (mCurrentRequests) {
        mCurrentRequests.add(request);
    }

    // Process requests in the order they are added.
    request.setSequence(getSequenceNumber());
    request.addMarker("add-to-queue");
    sendRequestEvent(request, RequestEvent.REQUEST_QUEUED);

    // 如果请求不需要缓存的话,直接交给网络请求队列去执行,默认是需要缓存的
    if (!request.shouldCache()) {
        mNetworkQueue.add(request);
        return request;
    }
    mCacheQueue.add(request);
    return request;
}
  

在这个方法中把请求交给了缓存队列或者网络队列去处理。

CacheDispatcher

CacheDispatcher继承自Thread,在RequestQueue#start()方法中已经将其启动了,因此直接看run方法:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  

public class CacheDispatcher extends Thread {
    private final BlockingQueue<Request<?>> mCacheQueue;
    private final BlockingQueue<Request<?>> mNetworkQueue;
    private final Cache mCache;
    private final ResponseDelivery mDelivery;
    private volatile boolean mQuit = false;

    /** Manage list of waiting requests and de-duplicate requests with same cache key. */
    private final WaitingRequestManager mWaitingRequestManager;

    public CacheDispatcher(
            BlockingQueue<Request<?>> cacheQueue,
            BlockingQueue<Request<?>> networkQueue,
            Cache cache,
            ResponseDelivery delivery) {
        mCacheQueue = cacheQueue;
        mNetworkQueue = networkQueue;
        mCache = cache;
        mDelivery = delivery;
        mWaitingRequestManager = new WaitingRequestManager(this);
    }

    public void quit() {
        mQuit = true;
        interrupt();
    }

    @Override
    public void run() {
        if (DEBUG) VolleyLog.v("start new dispatcher");
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

        // Make a blocking call to initialize the cache.
        mCache.initialize();

        while (true) {
            try {
                processRequest();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    Thread.currentThread().interrupt();
                    return;
                }
                VolleyLog.e("Ignoring spurious interrupt of CacheDispatcher thread; " + "use quit() to terminate it");
            }
        }
    }

    private void processRequest() throws InterruptedException {
        // 阻塞式队列
        final Request<?> request = mCacheQueue.take();
        processRequest(request);
    }

    void processRequest(final Request<?> request) throws InterruptedException {
        request.addMarker("cache-queue-take");
        request.sendEvent(RequestQueue.RequestEvent.REQUEST_CACHE_LOOKUP_STARTED);

        try {
            // If the request has been canceled, don't bother dispatching it.
            if (request.isCanceled()) {
                request.finish("cache-discard-canceled");
                return;
            }

            // Attempt to retrieve this item from cache.
            Cache.Entry entry = mCache.get(request.getCacheKey());
            if (entry == null) {
                request.addMarker("cache-miss");
                // Cache miss; send off to the network dispatcher.
                if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                    mNetworkQueue.put(request);
                }
                return;
            }

            // If it is completely expired, just send it to the network.
            if (entry.isExpired()) {
                request.addMarker("cache-hit-expired");
                request.setCacheEntry(entry);
                if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                    mNetworkQueue.put(request);
                }
                return;
            }

            // We have a cache hit; parse its data for delivery back to the request.
            request.addMarker("cache-hit");
            Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
            request.addMarker("cache-hit-parsed");

            if (!response.isSuccess()) {
                request.addMarker("cache-parsing-failed");
                mCache.invalidate(request.getCacheKey(), true);
                request.setCacheEntry(null);
                if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                    mNetworkQueue.put(request);
                }
                return;
            }
            if (!entry.refreshNeeded()) {
                // 缓存不需要刷新,直接交给ResponseDelivery去处理
                mDelivery.postResponse(request, response);
            } else {
                // 软过期的缓存命中,可以分发缓存的response,但是我们还需要将请求发送到网络以进行刷新。
                request.addMarker("cache-hit-refresh-needed");
                request.setCacheEntry(entry);
                // Mark the response as intermediate.
                response.intermediate = true;

                if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                    // 将intermediate响应发回给用户,然后将请求转发到网络。
                    mDelivery.postResponse(
                            request,
                            response,
                            new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        // 如果缓存需要刷新,这个地方还需要再重新请求网络
                                        mNetworkQueue.put(request);
                                    } catch (InterruptedException e) {
                                        // Restore the interrupted status
                                        Thread.currentThread().interrupt();
                                    }
                                }
                            });
                } else {
                    // 该请求已添加到等待请求的列表中,以便在第一个请求返回时从第一个请求接收网络响应。
                    mDelivery.postResponse(request, response);
                }
            }
        } finally {
            request.sendEvent(RequestQueue.RequestEvent.REQUEST_CACHE_LOOKUP_FINISHED);
        }
    }
}
  

如果有缓存,就取出来去处理,没有或者过期等,就加入到网络请求队列中去请求,需要网络请求的有几个地方:

  1. 请求不需要缓存
  2. 请求在缓存中没有找到
  3. 请求的缓存过期
  4. 请求的缓存需要刷新

NetworkDispatcher

NetworkDispatcher

NetworkDispatcher也继承自Thread,它们在RequestQueue#start()方法中已经被启动了,因此直接看run方法:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  

public class NetworkDispatcher extends Thread {
    private final BlockingQueue<Request<?>> mQueue;
    private final Network mNetwork;
    private final Cache mCache;
    private final ResponseDelivery mDelivery;
    private volatile boolean mQuit = false;

    public NetworkDispatcher(
            BlockingQueue<Request<?>> queue,
            Network network,
            Cache cache,
            ResponseDelivery delivery) {
        mQueue = queue;
        mNetwork = network;
        mCache = cache;
        mDelivery = delivery;
    }

    public void quit() {
        mQuit = true;
        interrupt();
    }

    @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        while (true) {
            try {
                processRequest();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    Thread.currentThread().interrupt();
                    return;
                }
                VolleyLog.e("Ignoring spurious interrupt of NetworkDispatcher thread; " + "use quit() to terminate it");
            }
        }
    }

    private void processRequest() throws InterruptedException {
        Request<?> request = mQueue.take();
        processRequest(request);
    }

    void processRequest(Request<?> request) {
        long startTimeMs = SystemClock.elapsedRealtime();
        request.sendEvent(RequestQueue.RequestEvent.REQUEST_NETWORK_DISPATCH_STARTED);
        try {
            request.addMarker("network-queue-take");

            if (request.isCanceled()) {
                request.finish("network-discard-cancelled");
                request.notifyListenerResponseNotUsable();
                return;
            }

            addTrafficStatsTag(request);

            // 执行网络请求
            NetworkResponse networkResponse = mNetwork.performRequest(request);
            request.addMarker("network-http-complete");

            // If the server returned 304 AND we delivered a response already,
            // we're done -- don't deliver a second identical response.
            if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                request.finish("not-modified");
                request.notifyListenerResponseNotUsable();
                return;
            }

            // Parse the response here on the worker thread.
            Response<?> response = request.parseNetworkResponse(networkResponse);
            request.addMarker("network-parse-complete");

            // Write to cache if applicable.
            // TODO: Only update cache metadata instead of entire record for 304s.
            if (request.shouldCache() && response.cacheEntry != null) {
                mCache.put(request.getCacheKey(), response.cacheEntry);
                request.addMarker("network-cache-written");
            }

            // Post the response back.
            request.markDelivered();
            mDelivery.postResponse(request, response);
            request.notifyListenerResponseReceived(response);
        } catch (VolleyError volleyError) {
            volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
            parseAndDeliverNetworkError(request, volleyError);
            request.notifyListenerResponseNotUsable();
        } catch (Exception e) {
            VolleyLog.e(e, "Unhandled exception %s", e.toString());
            VolleyError volleyError = new VolleyError(e);
            volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
            mDelivery.postError(request, volleyError);
            request.notifyListenerResponseNotUsable();
        } finally {
            request.sendEvent(RequestQueue.RequestEvent.REQUEST_NETWORK_DISPATCH_FINISHED);
        }
    }
}
  

可以看到,在NetworkDispatcher中,最主要的就是调用了mNetwork.performRequest(request)执行网络请求,而在Network是个接口,具体实现类是BasicNetwork。

BasicNetwork


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  

public NetworkResponse performRequest(Request<?> request) throws VolleyError {
    long requestStart = SystemClock.elapsedRealtime();
    while (true) {
        // ...
        try {
            // ...
            httpResponse = mBaseHttpStack.executeRequest(request, additionalRequestHeaders);
            // return NetworkResponse
        } catch (SocketTimeoutException e) {
            attemptRetryOnException("socket", request, new TimeoutError());
        } catch (MalformedURLException e) {
            throw new RuntimeException("Bad URL " + request.getUrl(), e);
        } catch (IOException e) {
            int statusCode;
            if (httpResponse != null) {
                statusCode = httpResponse.getStatusCode();
            } else {
                throw new NoConnectionError(e);
            }
            VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
            NetworkResponse networkResponse;
            if (responseContents != null) {
                networkResponse =
                        new NetworkResponse(
                                statusCode,
                                responseContents,
                                /* notModified= */ false,
                                SystemClock.elapsedRealtime() - requestStart,
                                responseHeaders);
                if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED
                        || statusCode == HttpURLConnection.HTTP_FORBIDDEN) {
                    attemptRetryOnException(
                            "auth", request, new AuthFailureError(networkResponse));
                } else if (statusCode >= 400 && statusCode <= 499) {
                    // Don't retry other client errors.
                    throw new ClientError(networkResponse);
                } else if (statusCode >= 500 && statusCode <= 599) {
                    if (request.shouldRetryServerErrors()) {
                        attemptRetryOnException(
                                "server", request, new ServerError(networkResponse));
                    } else {
                        throw new ServerError(networkResponse);
                    }
                } else {
                    // 3xx? No reason to retry.
                    throw new ServerError(networkResponse);
                }
            } else {
                attemptRetryOnException("network", request, new NetworkError());
            }
        }
    }
}

// 请求重试
private static void attemptRetryOnException(
        String logPrefix, Request<?> request, VolleyError exception) throws VolleyError {
    RetryPolicy retryPolicy = request.getRetryPolicy();
    int oldTimeout = request.getTimeoutMs();

    try {
        retryPolicy.retry(exception);
    } catch (VolleyError e) {
        request.addMarker(String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));
        throw e;
    }
    request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));
}

public class DefaultRetryPolicy implements RetryPolicy {
    @Override
    public void retry(VolleyError error) throws VolleyError {
        mCurrentRetryCount++;
        mCurrentTimeoutMs += (int) (mCurrentTimeoutMs * mBackoffMultiplier);
        if (!hasAttemptRemaining()) {
            throw error;
        }
    }

    /** Returns true if this policy has attempts remaining, false otherwise. */
    protected boolean hasAttemptRemaining() {
        return mCurrentRetryCount <= mMaxNumRetries;
    }
}
  

在BasicNetwork#performRequest()中调用了httpResponse = mBaseHttpStack.executeRequest(request, additionalRequestHeaders);,这里的mBaseHttpStack就是前面创建RequestQueue时新建的HurlStack和HttpClientStack(@Deprecated,上面RequestQueue的构造函数中还有个新建了HttpClientStack对象的方法,不过已经废弃了,不做解析)。因此在 HttpStack的executeRequest()中就是具体的网络请求。

HurlStack


1
2
3
4
5
6
7
  

public class HurlStack extends BaseHttpStack {
    @Override
    public HttpResponse executeRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError {
        // 这个类是使用HttpURLConnection来实现真的的网络请求,可以自定义
    }
}
  

ResponseDelivery

ResponseDelivery是一个接口:


1
2
3
4
5
6
7
8
9
10
11
12
13
  

public interface ResponseDelivery {
    /** Parses a response from the network or cache and delivers it. */
    void postResponse(Request<?> request, Response<?> response);

    /**
     * Parses a response from the network or cache and delivers it. The provided Runnable will be
     * executed after delivery.
     */
    void postResponse(Request<?> request, Response<?> response, Runnable runnable);

    /** Posts an error for the given request. */
    void postError(Request<?> request, VolleyError error);
}
  

具体实现类是ExecutorDelivery,它保证了客户端调用的回调运行在UI线程:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  

public class ExecutorDelivery implements ResponseDelivery {
    private final Executor mResponsePoster;
    // 在上面的分析中可以看到这里的handle = new Handler(Looper.getMainLooper())
    public ExecutorDelivery(final Handler handler) {
        mResponsePoster = new Executor() {
                @Override
                public void execute(Runnable command) {
                    handler.post(command);
                }
            };
    }

    public ExecutorDelivery(Executor executor) {
        mResponsePoster = executor;
    }

    @Override
    public void postResponse(Request<?> request, Response<?> response) {
        postResponse(request, response, null);
    }

    @Override
    public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
        request.markDelivered();
        request.addMarker("post-response");
        mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
    }

    @Override
    public void postError(Request<?> request, VolleyError error) {
        request.addMarker("post-error");
        Response<?> response = Response.error(error);
        mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null));
    }

    private static class ResponseDeliveryRunnable implements Runnable {
        private final Request mRequest;
        private final Response mResponse;
        private final Runnable mRunnable;

        public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
            mRequest = request;
            mResponse = response;
            mRunnable = runnable;
        }

        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            if (mRequest.isCanceled()) {
                mRequest.finish("canceled-at-delivery");
                return;
            }

            // 这里会调用在创建Request时传入的回调
            if (mResponse.isSuccess()) {
                mRequest.deliverResponse(mResponse.result);
            } else {
                mRequest.deliverError(mResponse.error);
            }

            if (mResponse.intermediate) {
                mRequest.addMarker("intermediate-response");
            } else {
                mRequest.finish("done");
            }

            // 如果有需要执行的任务,如前面缓存需要刷新等,就会在这个地方进行调用
            if (mRunnable != null) {
                mRunnable.run();
            }
        }
    }
}
  

总结

Volley中主要的类有这些:

  • Volley: 提供了构建RequestQueue的统一方法,我们也可以不通过Volley类而是自己构建RequestQueue;
  • RequestQueue: 负责分发请求到不同的请求队列中;
  • CacheDispatcher: 处理缓存请求;
  • NetworkDispatcher: 处理网络请求;
  • ResponseDelivery: 获取请求后进行处理,具体实现类为ExecutorDelivery;
  • Cache: 缓存接口,具体实现类有DiskBasedCache;
  • Network: 网络接口,具体实现类有BasicNetwork;
  • HttpStack: 真正执行请求,具体实现类有HttpClientStack(已废弃),BaseHttpStack(子类有HurlStack,AdaptedHttpStack等);
  • Request: 封装请求信息并处理回调,具体实现类有StringRequest,JsonRequest,ImageRequest等;
  • NetworkResponse:请求网络时的返回的response;
  • Response: 定义了一些回调接口,用来封装返回给客户端的数据。

Volley框架的拆装性很强,可以使用许多我们自定义的类来扩展其功能:

  • Request:框架默认提供了StringRequest,JsonRequest和ImageRequest等,我们可以继承Request并重写deliverResponse()和parseNetworkResponse()来自定义请求。
  • Cache:框架默认提供了DiskBasedCache类来处理缓存,我们可以继承Cache接口来自定义缓存策略。
  • HttpStack:框架默认使用的HurlStack类是通过HttpUrlConnection和HttpClient来实现网络请求,我们可以换成其它的比如说OkHttp,只需要继承HttpStack并重写performRequest()来处理请求就可以了。

总结一下Volley网络请求的流程:

  • 首先创建请求队列RequestQueue,其中可以自定义相关类,在这里会启动了一个Cache Dispatcher和指定数目的Network Dispatcher;
  • 然后在CacheDispatcher中处理请求,若缓存可用,则直接返回缓存,否则请求网络;
  • 接着在NetworkDispatcher中处理网络请求,真正起作用的是HttpStack实现类;
  • 最后通过ResponseDelivery实现类返回请求结果。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Volley源码解析 的相关文章

  • Spring源码解析7-(xml)Spring的AOP

    配置文件 直接看refresh 中的obtainFreshBeanFactory xff0c 初始化容器 xff0c 加载配置文件成beanDefinition 直接到DefaultBeanDefinitionDocumentReader的
  • Spring Security 解析(七) —— Spring Security Oauth2 源码解析

    在学习Spring Cloud 时 xff0c 遇到了授权服务oauth 相关内容时 xff0c 总是一知半解 xff0c 因此决定先把Spring Security Spring Security Oauth2 等权限 认证相关的内容 原
  • Guava-Collections2源码解析

    构造器 private Collections2 私有构造器 xff0c 也没有静态构造器 xff0c 所以可以很明确它是一个纯工具类了 功能方法 filter过滤方法 传入一个带过滤的容器 xff0c 和一个实现过滤规则的函数类 xff0
  • 机器人地面站-[QGroundControl源码解析]-[1]

    目录 前言 一 CmdLineOptParser 二 JsonHelper 三 KMLDomDocument 四 ShapeFileHelper 五 SHPFileHelper 六 KMLHelper 七 LogCompressor 总结
  • FREERTOS源码解析——heap4.c

    目录 内存管理heap4无法解决的内存碎片 xff1a HEAP4简析分配内存在哪 xff0c 大小多少如何管理 重要源码解析 内存管理 freertos目前提供了以下5种内存管理 xff0c 特点如下 heap1 xff1a 最简单的内存
  • DataBinding源码解析

    DataBinding是Google发布的支持库 xff0c 它可以实现UI组件及数据源的双向绑定 使用DataBinding可以轻松实现MVVM模式 xff0c 当数据发生变化时会体现在View界面上 xff0c 反过来界面内容变化也会同
  • Gson源码解析

    Gson简介 Gson xff0c 就是帮助我们完成序列化和反序列化的工作的一个库 日常用法 UserInfo userInfo 61 getUserInfo Gson gson 61 new Gson String jsonStr 61
  • Android Volley源码分析(1)

    1 Volley newRequestQueue 我们从Volley中RequestQueue的初始化入手 xff0c 开始进行分析 应用利用Volley java的静态方法 xff0c 获取RequestQueue xff0c 开启使用V
  • OkHttp-ConnectInterceptor源码解析

    ConnectInterceptor源码解析 本文基于okhttp3 10 0 1 概述 ConnectInterceptor主要是用于建立连接 xff0c 并再连接成功后将流封装成对象传递给下一个拦截器CallServerIntercep
  • Axios源码解析(部分)

    从 Github 上把 Axios 项目的 master 分支拷贝到本地 xff0c 用编辑器打开项目目录 首先我们先解析一下整个 Axios 项目的一些关键的文件结构 对照项目的文件目录 xff0c 梳理一下其中的一些关键文件夹以及它的作
  • FreeRTOS源码解析 -> vTaskDelete()

    vTaskDelete API 函数 任务可以使用API函数vTaskDelete 删除自己或其它任务 任务被删除后就不复存在 xff0c 也不会再进入运行态 空闲任务的责任是要将分配给已删除任务的内存释放掉 因此有一点很重要 xff0c
  • mc_att_control源码解析

    目录 源码分析内环控制外环控制 之前写了博客分析了一下旋翼姿态控制的基础知识 mc att control基础知识 这次就对照代码将整个旋翼姿态控制过程呈现一遍 先看一下整个程序的框图 从图中可以看到 实际上整个控制分成内外两个环进行控制
  • ConcurrentHashMap -1.8 源码解析

    ConcurrentHashMap 1 8 源码解析 加锁机制 在JDK1 7之前 xff0c ConcurrentHashMap是通过分段锁机制来实现的 xff0c 所以其最大并发度受Segment的个数限制 因此 xff0c 在JDK1
  • Libev源码解析

    最近在看libev源码 xff0c 算是对libev的源码有个比较清晰的了解 总共分3部分来介绍libev 1 Libev是什么 Libev是基于Reactor模式的一个高性能 xff0c 支持高并发的事件库 它本身不仅支持IO xff0c
  • java源码解析JavaParser

    package com bootdo jparser import java io File import java io FileNotFoundException import com github javaparser JavaPar
  • Pytorch学习(3) —— nn.Parameter nn.ParameterList nn.ParameterDict 源码解析

    为了更好理解Pytorch基本类的实现方法 xff0c 我这里给出了关于参数方面的3个类的源码详解 此部分可以更好的了解实现逻辑结构 xff0c 有助于后续代码理解 xff0c 学pytorch的话这个不是必须掌握的 xff0c 看不懂也没
  • ASCII表

    http office microsoft com zh cn assistance HA011331362052 aspx ASCII 打印字符 数字 32 126 分配给了能在键盘上找到的字符 当您查看或打印文档时就会出现 数字 127
  • 对象池(连接池):commons-pool2源码解析:GenericObjectPool的borrowObject方法

    为什么会有对象池 在实际的应用工程当中 存在一些被频繁使用的 创建或者销毁比较耗时 持有的资源也比较昂贵的一些对象 比如 数据库连接对象 线程对象 所以如果能够通过一种方式 把这类对象统一管理 让这类对象可以被循环利用的话 就可以减少很多系
  • Hashmap源码详解

    在开发中的对于数据结构如何选 我们要知道各个数据结构的优缺点 数组 采用一段连续的存储单元来存储数据 对于指定下标的查找 时间复杂度为O 1 但在数组中间以及头部插入数据时 需要复制移动后面的元素O n 优点 查找快 缺点插入慢 链表 一种
  • 对象池(连接池):commons-pool2源码解析:GenericObjectPool的继承结构、构造方法

    概述 GenericObjectPool是apache commons pool 源码分析基于commons pool2 框架中的一个非常重要的类 解析GenericObjectPool就有必要先了解一下apache commons poo

随机推荐