java - Volley 静态回调监听器上下文 GCed

标签 java android memory-leaks android-volley

使用后LeakCanary我发现我的应用程序中有很多泄漏,其中大部分是由于 Volley 的匿名回调监听器造成的。所以我写了一个 Util(下面)类,它使用静态回调和 WeakReference 来保持对 Context 和匿名回调的引用。但是当我第一次打开应用程序时,即冷启动,在发出请求后很快就会对上下文进行 GC,但在热启动期间一切正常。此外,这仅发生在应用程序中的第一个 Activity 中。

我们也欢迎任何可以正常工作的 volley 处理内存泄漏的替代方法。

public abstract class VUtil {

    public static final String TAG = VUtil.class.getSimpleName();

    public interface JsonCallback {
        void onSuccess(JSONObject response);
    }

    public interface StringCallback {
        void onSuccess(String response);
    }

    public interface ErrorCallback {
        void onError(VolleyError error);
    }

    public static class JsonResponseListener implements Response.Listener<JSONObject> {
        private final WeakReference<Context> mContextWeakReference;
        private final WeakReference<JsonCallback> mCallbackWeakReference;

        public JsonResponseListener(Context context, JsonCallback callback) {
            mContextWeakReference = new WeakReference<>(context);
            mCallbackWeakReference = new WeakReference<>(callback);
        }

        @Override
        public void onResponse(JSONObject jsonObject) {
            Context context = mContextWeakReference.get();
            JsonCallback callback = mCallbackWeakReference.get();
            if (context != null && callback != null) {
                callback.onSuccess(jsonObject);
            } else {
                Log.d(TAG, "Context was GCed");
            }
        }
    }

    public static class StringResponseListener implements Response.Listener<String> {
        private final WeakReference<Context> mContextWeakReference;
        private final WeakReference<StringCallback> mCallbackWeakReference;

        public StringResponseListener(Context context, StringCallback callback) {
            mContextWeakReference = new WeakReference<>(context);
            mCallbackWeakReference = new WeakReference<>(callback);
        }

        @Override
        public void onResponse(String response) {
            Context context = mContextWeakReference.get();
            StringCallback callback = mCallbackWeakReference.get();
            if (context != null && callback != null) {
                callback.onSuccess(response);
            } else {
                Log.d(TAG, "Context was GCed");
            }
        }
    }

    public static class ErrorListener implements Response.ErrorListener {

        private final WeakReference<Context> mContextWeakReference;
        private final WeakReference<ErrorCallback> mCallbackWeakReference;

        public ErrorListener(Context context, ErrorCallback callback) {
            mContextWeakReference = new WeakReference<>(context);
            mCallbackWeakReference = new WeakReference<>(callback);
        }

        @Override
        public void onErrorResponse(VolleyError error) {
            Context context = mContextWeakReference.get();
            ErrorCallback callback = mCallbackWeakReference.get();
            if (context != null && callback != null) {
                callback.onError(error);
            } else {
                Log.d(TAG, "Context was GCed");
            }
        }
    }
}

最佳答案

GC 取决于正在发生的许多事情。您的情况的一个可能原因是,当您在“冷启动”后执行第一个请求时,您的应用程序必须初始化各种自定义对象、 fragment 、 Activity 、 View 缓存等,因此在增加堆之前需要内存,从而执行 GC。

不过,我建议的解决方案是更改您的架构。

1) 似乎你保留了对上下文的引用,但它从未被使用过。放下它

2) 您有 Volley 回调委托(delegate)给您无论如何都需要传递的自定义回调,为什么不简单地使用一组传递给相应请求的回调。

3) 你 WeekRef 你的自定义回调,但你不能没有它们。 Week Referencing 并不是内存泄漏的最终解决方案。你必须找出为什么当你不需要它时 ref 仍然存在。

因此,如果您在 JsonCallback、StringCallback 和 ErrorCallback 实现中出现泄漏问题,只需尝试解决这个问题,而不是让链变长并在末尾切断它。

关于java - Volley 静态回调监听器上下文 GCed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36260450/

相关文章:

java - 当我使用字符串作为文件名时,eclipse 扫描仪 filenotfoundException

Android:Google Fused Location 在位置关闭时不起作用

java - 安卓/Java : why does my ConstraintLayout leak?

ruby-on-rails - Ruby on Rails 内存管理

Java:从System.in读取时InputStream的read()方法在哪里实现

java - Jmeter Socket中的TCP Sampler连接错误

java - 如何在 Android 中有效地管理多个异步任务

Android Studio 无法让模拟器运行

android - onPause/onRestore 与 savedInstanceState

java - Spring + MongoDB : potential memory leak messages