我是否应该担心内存泄漏并在Android中使用WeakReference和Volley

时间:2014-10-28 01:44:07

标签: android android-volley

在阅读this article后,我开始考虑与Volley的内存泄漏。 通常,使用Volley实现的侦听器具有对外部类(活动)的隐式或显式引用。例如:

JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
        url, null, 
        new Response.Listener<JSONObject>() {
            @Override 
            public void onResponse(JSONObject response) {

                updateLayout(); 
            } 
        }

在这种情况下有一个隐式引用...或者我可能想创建一个自定义JsonObjectRequest来内化响应处理,并且需要在其构造函数中传入对调用活动的引用。

现在让我说我开始一个Web请求,但在响应回来之前,我离开了启动请求的活动。根据我的理解,JsonObjectRequest对象将保留对我的活动的引用并防止它被垃圾收集。
- 我理解这一点,这是一种合理的恐惧吗?
- Volley图书馆会自动处理这个吗?
- 如果我正在创建一个自定义的JsonObjectRequest并传入一个&#34;这个&#34; (参考活动),我是否需要为活动创建一个WeakReference?

3 个答案:

答案 0 :(得分:5)

根据查看凌空代码,调用cancel并不能真正避免内存泄漏,因为引用永远不会被清除,引用也不会很弱。调用取消只会避免Volley将响应传递给听众。

我对问题的解决方案必须自己克隆和修改库。

  • 其中一个解决方案可以是将基础Request.java中的基本ErrorListener引用作为弱引用。类似地,可以对JsonRequest.java中的Listener进行相同的操作。

  • 另一种解决方案是在取消被调用时手动清除引用。在cancel()内部,将mErrorListener和mListener设置为null。但是,使用此解决方案,您必须从字段声明中删除最终修饰符,否则您将无法将引用设置为null。

希望这有帮助。

答案 1 :(得分:2)

我在使用凌空时遇到了内存泄漏,就像你在这里写的那样。每次我都是新的听众。

我用泄漏检测泄漏。

当我读到您的文章http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html,并将WeakReference用于活动和回调界面(我自定义)时,它就解决了。

我用排球作为单身人士。

public interface VolleyCallback {
    void onSuccess(JSONObject result);

    void onFailed(String error);
}

private static class SListener implements Response.Listener<JSONObject> {
    private final WeakReference<Activity> activityWeakReference;
    private final WeakReference<VolleyCallback> callbackWeakReference;

    public SListener(Activity activity, VolleyCallback callback) {
        activityWeakReference = new WeakReference<Activity>(activity);
        callbackWeakReference = new WeakReference<VolleyCallback>(callback);
    }

    @Override
    public void onResponse(JSONObject jsonObject) {
        Activity act = activityWeakReference.get();
        VolleyCallback vc = callbackWeakReference.get();
        if (act != null && vc != null) {
            LogUtil.d(TAG, act.toString() + "   " + jsonObject.toString());
            something you need to do;
            vc.onSuccess(jsonObject);
        }
    }

我也读了这个答案,How to use WeakReference in Java and Android development?,第二个答案给出了一个例子,就像你提供的文章一样。这很好。

答案 2 :(得分:1)

我可能迟到了一年,但我只想找到解决这个问题的方法。这是:

public interface VolleyCallback { 
    void onSuccess(JSONObject result);

    void onFailed(String error);
} 

private static class SListener implements VolleyCallback {
    private final WeakReference<MainActivity> activityWeakReference;

    public SListener(MainActivity activity, VolleyCallback callback) {
        activityWeakReference = new WeakReference<>(activity);
    } 
@Override
    void onSuccess(JSONObject result){
}
 @Override
    void onFailed(String error){
   }
  } 

这里你可以使用activityWeakReference.get()来访问MainActivity的所有UI元素。 从http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html找到了这个。这样我们就不需要取消onStop()中的任何请求。请记得使用activityWeakReference.get().isFinishing&amp;&amp; activityWeakReference.get()!=null以避免在活动不存在时崩溃。