diff options
author | Anonymous <no-reply@google.com> | 2017-11-10 14:35:22 -0800 |
---|---|---|
committer | Jeff Davidson <jpd@google.com> | 2017-11-10 15:04:47 -0800 |
commit | 03032767fe4ba272fb2efe759660d62b6779c05d (patch) | |
tree | 4dfbfc4f0056f5f7fe94057c4bff2a1d02039083 /src/main | |
parent | fa08a1a64c39d7a4b8699912603e6580e00ba71d (diff) | |
download | volley-03032767fe4ba272fb2efe759660d62b6779c05d.tar.gz |
Import of Volley from GitHub to AOSP.
- 536c1b741d18395a8aa041de484f3dc46fb57692 Workaround memory leak in dispatchers. (#119) by Jeff Davidson <jpd236@cornell.edu>
- c3bd8e933bbf30f08ac388575ed168006db3f47b Bump from 1.0.1-SNAPSHOT to 1.1.0-SNAPSHOT. (#107) by Jeff Davidson <jpd236@cornell.edu>
GitOrigin-RevId: 536c1b741d18395a8aa041de484f3dc46fb57692
Change-Id: If6ad78873506502a88f5677df6fbec62a51edf07
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/com/android/volley/CacheDispatcher.java | 145 | ||||
-rw-r--r-- | src/main/java/com/android/volley/NetworkDispatcher.java | 106 |
2 files changed, 132 insertions, 119 deletions
diff --git a/src/main/java/com/android/volley/CacheDispatcher.java b/src/main/java/com/android/volley/CacheDispatcher.java index b0432f3..cd3635d 100644 --- a/src/main/java/com/android/volley/CacheDispatcher.java +++ b/src/main/java/com/android/volley/CacheDispatcher.java @@ -93,82 +93,89 @@ public class CacheDispatcher extends Thread { while (true) { try { - // Get a request from the cache triage queue, blocking until - // at least one is available. - final Request<?> request = mCacheQueue.take(); - request.addMarker("cache-queue-take"); - - // If the request has been canceled, don't bother dispatching it. - if (request.isCanceled()) { - request.finish("cache-discard-canceled"); - continue; + processRequest(); + } catch (InterruptedException e) { + // We may have been interrupted because it was time to quit. + if (mQuit) { + 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); - } - continue; - } + // Extracted to its own method to ensure locals have a constrained liveness scope by the GC. + // This is needed to avoid keeping previous request references alive for an indeterminate amount + // of time. Update consumer-proguard-rules.pro when modifying this. See also + // https://github.com/google/volley/issues/114 + private void processRequest() throws InterruptedException { + // Get a request from the cache triage queue, blocking until + // at least one is available. + final Request<?> request = mCacheQueue.take(); + request.addMarker("cache-queue-take"); - // 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); - } - continue; - } + // If the request has been canceled, don't bother dispatching it. + if (request.isCanceled()) { + request.finish("cache-discard-canceled"); + 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"); + // 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 (!entry.refreshNeeded()) { - // Completely unexpired cache hit. Just deliver the response. - mDelivery.postResponse(request, response); - } else { - // Soft-expired cache hit. We can deliver the cached response, - // but we need to also send the request to the network for - // refreshing. - request.addMarker("cache-hit-refresh-needed"); - request.setCacheEntry(entry); - // Mark the response as intermediate. - response.intermediate = true; + // 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; + } - if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) { - // Post the intermediate response back to the user and have - // the delivery then forward the request along to the network. - 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 { - // request has been added to list of waiting requests - // to receive the network response from the first request once it returns. - mDelivery.postResponse(request, response); - } - } + // 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"); - } catch (InterruptedException e) { - // We may have been interrupted because it was time to quit. - if (mQuit) { - return; - } + if (!entry.refreshNeeded()) { + // Completely unexpired cache hit. Just deliver the response. + mDelivery.postResponse(request, response); + } else { + // Soft-expired cache hit. We can deliver the cached response, + // but we need to also send the request to the network for + // refreshing. + request.addMarker("cache-hit-refresh-needed"); + request.setCacheEntry(entry); + // Mark the response as intermediate. + response.intermediate = true; + + if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) { + // Post the intermediate response back to the user and have + // the delivery then forward the request along to the network. + 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 { + // request has been added to list of waiting requests + // to receive the network response from the first request once it returns. + mDelivery.postResponse(request, response); } } } diff --git a/src/main/java/com/android/volley/NetworkDispatcher.java b/src/main/java/com/android/volley/NetworkDispatcher.java index 0384429..2c04ce0 100644 --- a/src/main/java/com/android/volley/NetworkDispatcher.java +++ b/src/main/java/com/android/volley/NetworkDispatcher.java @@ -83,70 +83,76 @@ public class NetworkDispatcher extends Thread { public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); while (true) { - long startTimeMs = SystemClock.elapsedRealtime(); - Request<?> request; try { - // Take a request from the queue. - request = mQueue.take(); + processRequest(); } catch (InterruptedException e) { // We may have been interrupted because it was time to quit. if (mQuit) { return; } - continue; } + } + } - try { - request.addMarker("network-queue-take"); - - // If the request was cancelled already, do not perform the - // network request. - if (request.isCanceled()) { - request.finish("network-discard-cancelled"); - request.notifyListenerResponseNotUsable(); - continue; - } - - addTrafficStatsTag(request); + // Extracted to its own method to ensure locals have a constrained liveness scope by the GC. + // This is needed to avoid keeping previous request references alive for an indeterminate amount + // of time. Update consumer-proguard-rules.pro when modifying this. See also + // https://github.com/google/volley/issues/114 + private void processRequest() throws InterruptedException { + long startTimeMs = SystemClock.elapsedRealtime(); + // Take a request from the queue. + Request<?> request = mQueue.take(); + + try { + request.addMarker("network-queue-take"); + + // If the request was cancelled already, do not perform the + // network request. + if (request.isCanceled()) { + request.finish("network-discard-cancelled"); + request.notifyListenerResponseNotUsable(); + return; + } - // Perform the network request. - NetworkResponse networkResponse = mNetwork.performRequest(request); - request.addMarker("network-http-complete"); + addTrafficStatsTag(request); - // 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(); - continue; - } + // Perform the network request. + NetworkResponse networkResponse = mNetwork.performRequest(request); + request.addMarker("network-http-complete"); - // Parse the response here on the worker thread. - Response<?> response = request.parseNetworkResponse(networkResponse); - request.addMarker("network-parse-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; + } - // 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"); - } + // Parse the response here on the worker thread. + Response<?> response = request.parseNetworkResponse(networkResponse); + request.addMarker("network-parse-complete"); - // 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(); + // 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(); } } |