Volley引起的内存泄漏--安卓怎么查内存泄漏(下)

怎么处理volley的内存泄漏呢
网上查了查,有说是volley的低版本的bug 升级版本 就好了 但是项目里的volley是down下来的包,改了内部很多东西,比较难直接升级。so.. 只能现在这个基础上解决问题。

1.先看mat分析出来的 强引用路径

《Volley引起的内存泄漏--安卓怎么查内存泄漏(下)》 Eclipse Memory Analyzer MemoryAnalyzer, 前天 at 22.39.32.png

最下面是被StringRequest引用着,他引用着requestNet:网络请求的工具类,又引用着另一个中间层封装的工具类,最后就是不能被回收的内存大头。

  1. 肯定是把不能回收的活动的引用传入了StringRequest里面,有了强引用关系导致的。检查代码,发现是网络请求的回调,项目都是实现一个回调的接口,请求网络把自己当listener,但是为什么不能被回收呢。即使网络请求完成了,也不行。

上网查了查,也有遇到这个问题的,有说把传入的引用声明为软引用或弱引用的。

java引用从强到弱分别是:强软弱虚 强引用:就是我们声明最多的引用,直接声明 软引用:不靠谱的引用,当内存不足时就回收(原来一直以为是oom之前回收,其实不是不是是不是) 弱引用:GC看到就是回收,更不靠谱的引用 虚引用:形同虚设,一般用在GC内部 当然能够回收的前提是没有任何强引用拉着它。

好了,既然有强引用引着它,那就把传入volley的activity引用声明为软引用或弱引用就行了呗,还是软引用吧,至少不会像弱引用那么不靠谱。好的开始做,嗯,果然被回收掉了。

但是有一个问题,时不时就会没有数据返回,因为网络的回调被回收了,一只转圈,体验极差。我一直认为软引用是在OOM发生前会回收的,其实不是。它是在GC回收完成后,可用内存如果小于10M(默认是这个值,app可用内存越多,这个值就越大)时就会回收(没有其他强引用拉着)。所以说非常非常容易被回收的。很不靠谱。

*** 所以声明成软引用是不行的。***

为什么回收不掉呢,想了想可能和线程的方法栈有关,volley内部有一个线程池,这个线程执行完后,没有停止或回收里面的线程,导致方法栈(GCRoot)一只拉着不能回收。多请求几次网络,前几次的就能被回收了,确实有这个现象发生。看看volley有没有停止的方法吧,果然有。

这个一加就可以了。具体内部的细节还会再研究, 有知道的大神可以分享一下,谢谢啦。

    public void finish() {
        try {
            Volley.getReqQueue().stop();
        }catch (Exception e){
            e.printStackTrace();
        }
}







    原文作者:ZSACH
    原文地址: https://www.jianshu.com/p/c48d3466f412
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞