From 8e75d19d29d614c6453743a71a56178c752ce435 Mon Sep 17 00:00:00 2001 From: bshao Date: Thu, 25 Jun 2015 20:47:30 +0800 Subject: [PATCH] [fix] leaking the last request object after request queue is drained MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit description: this leak can be detected by LeakCanary, see D/LeakCanary﹕ In io.github.pandacast:1.1:2. D/LeakCanary﹕ * io.github.pandacast.MainActivity has leaked: D/LeakCanary﹕ * GC ROOT thread com.android.volley.NetworkDispatcher. (named 'Thread-5690') D/LeakCanary﹕ * references io.github.pandacast.model.RestClient$LiveListRequest.mListener D/LeakCanary﹕ * references io.github.pandacast.LiveListFragment$LiveListAdapter.mContext D/LeakCanary﹕ * leaks io.github.pandacast.MainActivity instance root cause: In NetworkDispatcher.run(), the local variable `request` hold the last Request object. If there is no more Request object in `mQueue`, `request = mQueue.take();` in line 90 would **block** until new Request object enqueue, which cause the leak of last Request object. In common pracice, Request has strong reference to Listener and Listener is either implmented by Activity or referenced by Activity as instance of inner class which implement Listener. Thus cause leaking the whole Activity instance. how to fix: set request to **null** before `request = mQueue.take();` --- src/main/java/com/android/volley/NetworkDispatcher.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/android/volley/NetworkDispatcher.java b/src/main/java/com/android/volley/NetworkDispatcher.java index beb78615..1775b186 100644 --- a/src/main/java/com/android/volley/NetworkDispatcher.java +++ b/src/main/java/com/android/volley/NetworkDispatcher.java @@ -82,9 +82,11 @@ private void addTrafficStatsTag(Request request) { @Override public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + Request request; while (true) { long startTimeMs = SystemClock.elapsedRealtime(); - Request request; + // release previous request object to avoid leaking request object when mQueue is drained. + request = null; try { // Take a request from the queue. request = mQueue.take();