Android排球内存泄漏

时间:2017-10-30 22:15:42

标签: android memory-leaks android-volley

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

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

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

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()但仍然有内存泄漏。

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

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

使用此版本:

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

3 个答案:

答案 0 :(得分:4)

仅仅将“将响应侦听器移动到他们自己的独立类”是不够的。 您的侦听器具有对活动(mContext)的强引用,在请求期间引入了泄漏。这意味着在请求正在进行时,您的活动无法进行垃圾回收。 这不是Volley的错,而是一种自然的方式。

您的案例中有几种选择:

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

2)在调用Activity的mContext时,在监听器中将null设置为onDestroy()。当您尝试在侦听器中使用Context执行某些操作时,也会执行空检查。因此,一旦Activity被销毁,您将删除其他强引用,允许GC正常收集它。

答案 1 :(得分:3)

请更新到最新的凌空版本,他们已修复内存泄漏。 &#39; com.android.volley:排:1.1.0-RC1&#39;

https://github.com/google/volley/releases/tag/1.1.0-rc1

答案 2 :(得分:-2)

您始终在创建新活动。请试试这个。在此处阅读更多相关信息:https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP

Intent mainIntent = new Intent(mContext, MainActivity.class);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivity(mainIntent);
相关问题