Summary of the article
1. volley Cache Thread Running Process
2. volley implementation decomposition steps
Attachment: Get Volley source code
Demos case source code: https://github.com/HailouWang/DemosForApi
I. CacheDispatcher threads
1. There are three threads in Volley, among which Cache Dispatcher is the cache thread.
2. CacheDispatcher buffer threads are designed to distribute Request requests by performing shunts in the buffer pool.
The thread runs in a loop, and the thread raw material comes from mCacheQueue. In the main thread, requests can be added to mCacheQueue through the RequestQueue.add method.-
3. Workflow can be simply summarized as the following steps:
- 1. The thread runs in a loop, and the thread material comes from mCacheQueue.
- 2. Get data from the buffer first. If there is data in the buffer, return the data directly to the main thread.
- 3. If the cache [does not hit data] or [cache data expires], the Request is distributed to the Network Dispatcher (network thread), which resynchronizes the data.
Annex: Flow chart
- Volley Cache Thread Flow Chart. png
II. Realization Analysis
1. The thread runs in a loop to get the Request object
while (true) { try { // Get a request from the cache triage queue, blocking until // at least one is available. //1. hlwang: Cache Dispatcher raw material from mCacheQueue, the first step is to obtain Request final Request<?> request = mCacheQueue.take(); request.addMarker("cache-queue-take"); ... ... } }
2. If the Request is cancelled by the user, no further execution is required.
// If the request has been canceled, don't bother dispatching it. //2. hlwang: If the request has been cancelled, there is no need to continue if (request.isCanceled()) { request.finish("cache-discard-canceled"); continue; }
3. Check the buffer first. If the data is not hit (i.e. the data does not exist), then send it to the Network thread to synchronize the data.
// Attempt to retrieve this item from cache. //3. hlwang: If there is no data in the cache, it means that it is new data, then give it to mNetworkQueue to synchronize the new data. Cache.Entry entry = mCache.get(request.getCacheKey()); if (entry == null) { request.addMarker("cache-miss"); // Cache miss; send off to the network dispatcher. mNetworkQueue.put(request); continue; }
4. If the cached data expires, it is still left to the Network thread to synchronize the data.
// If it is completely expired, just send it to the network. //4. hlwang: If the cache expires, it means that the data is too old and is given to mNetworkQueue to synchronize the new data. if (entry.isExpired()) { request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); mNetworkQueue.put(request); continue; }
5. When the cached data is hit, the cached data is parsed and the Response object is constructed.
// We have a cache hit; parse its data for delivery back to the request. //5. wanghailu: We hit a cache data (w found a cache hl during the shelf life), parsed the data and constructed the response object Response. request.addMarker("cache-hit"); Response<?> response = request.parseNetworkResponse( new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-parsed");
6. If the data is cached and need not be refreshed, the response data is called back to the user through Delivery.
if (!entry.refreshNeeded()) { // Completely unexpired cache hit. Just deliver the response. //6. If entry data does not need to be refreshed, use mDelivery to pass the response out mDelivery.postResponse(request, response); }
7. If the cached data needs to be updated again, the cached data will now be returned to the user, and then synchronous data requests will be initiated through the main thread.
// Soft-expired cache hit. We can deliver the cached response, // but we need to also send the request to the network for // refreshing. //7. Although hit by the cache, the data is slightly out of date. We can deliver and distribute cached response data. //But we also need to send requests to mNetworkQueue to refresh and update. request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); // Mark the response as intermediate. //7.1. Update response status as media response.intermediate = true; // Post the intermediate response back to the user and have // the delivery then forward the request along to the network. //7.2. Main Thread Distribution mDelivery.postResponse(request, response, new Runnable() { @Override public void run() { try { mNetworkQueue.put(request); } catch (InterruptedException e) { // Not much we can do about this. } }