使用LeakCanary后,我发现我的应用程序中存在许多泄漏,其中大多数是由于Volley的匿名回调侦听器造成的。因此,我编写了一个Util(下)类,该类使用静态回调和WeakReference保持对Context和匿名回调的引用。但是,当我第一次打开应用程序(即冷启动)时,在请求发出后不久便对GC进行了GC,但是在热启动期间一切正常。此外,这仅发生在应用程序中的第一个活动中。

也欢迎使用排球正确处理内存泄漏的任何其他方法。

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取决于许多正在发生的事情。造成这种情况的一个可能原因是,当您在“冷启动”后发出第一个请求时,应用程序必须初始化各种自定义对象,片段,活动,视图缓存等,因此在增加堆之前需要内存,因此需要进行GC。

但是,我建议的解决方案是更改您的体系结构。

1)似乎您一直引用上下文,但从未使用过。放下

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

3)您可以使用WeekRef自定义回调,但是如果没有它们,您将无法做到。周引用不是内存泄漏的最终解决方案。您必须找出为什么不需要引用时引用仍然存在的原因。

因此,如果泄漏问题出在JsonCallback,StringCallback和ErrorCallback实现中,请尝试解决此问题,而不是延长链并在末端将其切断。

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

10-12 00:31
查看更多