android - volley 请求的匿名监听器导致内存泄漏

标签 android web-services memory-leaks android-volley leakcanary

我正在使用 volley 库进行网络服务调用。我做了一个通用类,用于调用所有 Web 服务并从那里调用服务,并为成功和错误响应创建了匿名监听器。

但是当我使用 leak canary 时,它显示与上下文相关的内存泄漏。下面是我的代码 fragment :

public void sendRequest(final int url, final Context context, final ResponseListener responseListener, final Map<String, String> params) {
    StringRequest stringRequest;
    if (isNetworkAvailable(context)) {

      stringRequest = new StringRequest(methodType, actualURL + appendUrl, new Listener<String>() {
            @Override
            public void onResponse(String response) {
                dismissProgressDialog(context);
                try {
                    (responseListener).onResponse(url, response);
                } catch (JsonSyntaxException e) {
                    // Util.showToast(context, context.getResources().getString(R.string.error));
                    Crashlytics.logException(e);
                }
            }

        }, new ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // Util.showToast(context,context.getString(R.string.error));

                dismissProgressDialog(context);
                if (error instanceof NetworkError) {
                     Util.showToast(context, context.getResources().getString(R.string.network_error));
                } else if (error instanceof NoConnectionError) {
                     Util.showToast(context, context.getResources().getString(R.string.server_error));
                } else if (error instanceof TimeoutError) {
                     Util.showToast(context, context.getResources().getString(R.string.timeout_error));
                } else {
                     Util.showToast(context, context.getResources().getString(R.string.default_error));
                }


            }

        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                return params;
            }


            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                return request.getHeaders(context, actualURL, false);
            }
        };
        stringRequest.setRetryPolicy(new DefaultRetryPolicy(30000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        VolleySingleton.getInstance(context).addRequest(stringRequest);
    } else {
         Util.showToast(context, context.getString(R.string.internet_error_message));
    }
}

我还创建了一个名为响应监听器的接口(interface),用于将响应重定向到 Activity 或 fragment 。我提出如下要求。

Request.getRequest().sendRequest(Request.SOME URL, SplashScreenActivity.this, SplashScreenActivity.this, new HashMap<String, String>());

但我正面临内存泄漏:

In 2.1.1:31.
* activity.SplashScreenActivity has leaked:
* GC ROOT com.android.volley.NetworkDispatcher.<Java Local>
* references network.Request$5.mListener (anonymous subclass of com.android.volley.toolbox.StringRequest)
* references network.Request$3.val$responseListener (anonymous implementation of com.android.volley.Response$Listener)
* leaks activity.SplashScreenActivity instance
* Retaining: 1.2MB.
* Reference Key: b8e318ea-448c-454d-9698-6f2d1afede1e
* Device: samsung samsung SM-G355H kanas3gxx
* Android Version: 4.4.2 API: 19 LeakCanary: 1.4 6b04880
* Durations: watch=5052ms, gc=449ms, heap dump=2617ms, analysis=143058ms

任何消除此泄漏的想法都将受到任何帮助。

最佳答案

通常,匿名类对封闭类实例具有强引用。在您的情况下,这将是 SplashScreenActivity。现在我想,在您通过 Volley 从服务器获得响应之前,您的 Activity 已经完成。由于监听器对封闭 Activity 具有强引用,因此在 Anonymous 类完成之前,无法对 Activity 进行垃圾回收。你应该做的是标记你发送的所有请求与 Activity 实例,并在 Activity 的 onDestroy() 回调中取消所有请求。

stringRequest.setTag(activityInstance);

要取消所有待处理的请求:

requestQueue.cancellAll(activityInstance);

此外,使用 VolleySingleton 中的应用程序上下文来创建 RequestQueue。

mRequestQueue = Volley.newRequestQueue(applicationContext);

不要在那里使用您的 Activity 上下文,也不要在 VolleySingleton 中缓存您的 Activity 实例。

关于android - volley 请求的匿名监听器导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39630712/

相关文章:

java - 使用多个 if 值优化数组结果

java - 返回 ArrayList 的 SOAP 响应

linux - Delphi 创建的 Soap 服务器应用程序可以在 Linux 上运行吗?

.net - 导致 “Arithmetic operation resulted in overflow”错误的System.DirectoryServices.DirectorySearcher

Perl XS : create and return array of strings (char*) taken from calling a C function or undef on failure

android - asmack 流错误(主机未知)

java - 数据库调用后弹出对话框的时机

android - 如何在我的 Android 应用程序上播放 YouTube 360​​ 度全景视频?

java - JAXWS-RT : getting com. sun.xml.ws.spi.db.DatabindingException 绑定(bind)一个简单的类

haskell - 为什么我的并行遍历 Haskell 程序会泄漏内存?