Android Volley内存泄漏 [英] Android Volley Memory Leaks

查看:90
本文介绍了Android Volley内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Google的凌空库,并且我一直在努力解决应用程序中的内存泄漏问题.我做了太多的研究,已经做了太多的尝试,但是现在我不知道该怎么办.这是一个示例代码:

I use google's volley library and I have been battling memory leaks in my apps for weaks now. I have done soo much research and tried soo much already but now I just do not know what to do. This is a sample code:

SplashActivity.java

SplashActivity.java

public class SplashActivity extends AppCompatActivity {

    Context mContext;
    AuthRequest mAuthRequest;
    GetTokenOnSuccessListener mGetTokenOnSuccessListener;
    GetTokenOnErrorListener mGetTokenOnErrorListener;
    private ConfigTable mConfigTable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialiseViewsAndComponents();
    }

    @Override
    protected void onStart() {
        super.onStart();
        getAuthToken();
    }

    private void initialiseViewsAndComponents() {
        mContext = SplashActivity.this;
        mAuthRequest = new AuthRequest(mContext);
        mGetTokenOnSuccessListener = new GetTokenOnSuccessListener(mContext);
        mGetTokenOnErrorListener = new GetTokenOnErrorListener(mContext);
        mConfigTable = new ConfigTable(mContext);
    }

    private void getAuthToken() {
        if (!mConfigTable.get("INITIALISED").equals("")) {
            mAuthRequest.guest(mGetTokenOnSuccessListener, mGetTokenOnErrorListener);
        } else {
            Intent mainIntent = new Intent(mContext, MainActivity.class);
            startActivity(mainIntent);
        }
    }

}

GetTokenOnSuccessListener.java

GetTokenOnSuccessListener.java

public class GetTokenOnSuccessListener implements Response.Listener<JSONObject> {

    //private Activity mActivity;
    private Context mContext;
    private ConfigTable mConfigTable;
    private int mSuccess = 0;
    private String mMessage = "";

    public GetTokenOnSuccessListener(Context context) {
        //this.mActivity = context;
        this.mContext = context;
        this.mConfigTable = new ConfigTable(this.mContext);
    }

    @Override
    public void onResponse(JSONObject response) {
        try {
            mSuccess = Integer.parseInt(response.get("success").toString());
            mMessage = response.get("message").toString();

            if (mSuccess == 1) {
                mConfigTable.setAuthToken(response.get("message").toString());
                Intent mainIntent = new Intent(mContext, MainActivity.class);
                mContext.startActivity(mainIntent);
                ((SplashActivity) mContext).finish();
            } else {
                Toast.makeText(mContext, "Lol access denied, could not retrieve token from server.", Toast.LENGTH_SHORT).show();
            }


        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(mContext, "Lol access denied, could not retrieve token from server.", Toast.LENGTH_SHORT).show();
        }
    }
}

GetTokenOnErrorListener.java

GetTokenOnErrorListener.java

public class GetTokenOnErrorListener implements Response.ErrorListener {

    private Context mContext;

    public GetTokenOnErrorListener(Context context) {
        this.mContext = context;
    }

    @Override
    public void onErrorResponse(VolleyError error) {
        Utils.showNetworkResponse(mContext, error);
    }
}

好吧,现在我根据在网上阅读的内容将响应侦听器移到了自己的单独的类中,以为它可以解决泄漏,但不能.我添加了代码以根据请求的标签取消所有待处理的请求 onDestroy(),但仍然存在内存泄漏.

Okay now I moved the response listeners to their own separate classes based on something I read online thinking it will resolve the leak but no it did not. I added code to cancel all pending requests onDestroy() based on the request's tag but still I had memory leaks.

这只是我的启动活动,这里的泄漏很小,我感觉是因为我调用了finish(),但我没有得到,因为我在请求成功完成后调用了它.我所有其他活动的代码都相似,但是会泄漏更多的内存, 11mb .

This is just my splash activity and the leaks here are small, I have a feeling it's because I call finish() but I don't get that because I call it after the request has been completed successfully. All my other activities have similar codes but leak more memory as much as 11mb.

所以我的问题是有人在凌空图书馆工作吗?如何使用它并避免内存泄漏?

So my question is has anyone worked with the volley library? How do I use it and avoid memory leaks?

使用此版本:

compile 'com.android.volley:volley:1.0.0'

推荐答案

仅将响应侦听器移动到他们自己的单独类中"是不够的. 您的侦听器对活动(mContext)具有很强的引用,从而在请求期间引入了泄漏.这意味着在请求正在进行时,您的活动无法被垃圾回收. 这并不是Volley的错,而是自然的事情.

It's not enough just to "Move response listeners to their own separate classes". Your listeners have strong references to the Activity (mContext), introducing a leak during the request. It means that your Activity can't be garbage collected, while the request is ongoing. It's not really a Volley's fault, but rather a natural way of things.

在您的情况下,您有几种选择:

You have couple of options in your case:

1)将WeakReference<Context>传递给您的侦听器,而不是对Context的强引用.这样,您就不会引入泄漏,并且在您尝试访问它时,必须检查此引用的Context是否还没有为null.但我宁愿选择第二个选项.

1) Pass a WeakReference<Context> to your listeners, instead a strong reference to Context. This way you won't introduce a leak and will have to check if this referenced Context isn't yet null, when you try to access it. But I'd rather go for the 2nd option.

2)在调用Activity的onDestroy()时,在侦听器中将mContext设置为null.当您尝试在侦听器中使用Context进行操作时,还要执行null检查.因此,一旦Activity被销毁,您将删除对其的其他强引用,从而使GC可以正常收集它.

2) Set mContext to null in listeners, when Activity's onDestroy() is called. And perform null check as well, when you are trying to do something with Context in listener. So as soon as Activity will be destroyed, you'll remove other strong references to it, allowing GC to collect it normally.

这篇关于Android Volley内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆