讲个故事,那天发现一个问题,在segmentfault上搜到一个提问:
有没有人用android做过类似的事情,其中一个activity里面一有一百多张图片,如果反复进入该activity就会导致溢出。
已经测试过universal-imageloader,picasso、fresco工具,都不理想,或者是我使用方法的问题。求大神指点!!
我就提问给楼主:
兄弟我最近也遇到这个问题了,也是试过universal-imageloader,picasso,fresco,请问你是怎么解决的
楼主回:
android:largeHeap="true" .....这个问题的水很深,谷歌的解决方案都不会完全没有内存泄漏的问题。
刚开始时候我怀疑是系统的问题,然后网上开始搜,发现遇到这个问题的人并不多,我猜可能是因为他们图片加载比较少。楼主给的方案我早就知道了,一看就不行,只是分配的内存多了一点而已。却发现了内存泄漏,然后怀疑是图片缓存的问题,因为这几个图片加载工具都是支持图片缓存的,于是开始搜imageloader内存泄漏,发现了《使用AndroidStudio分析和解决ImageLoader引起内存泄露问题》这篇文章。
我当时以为我找到了答案,说的很有道理,也真的有用。就是把imageloader加载后生成的bitmap给手动回收掉。
我当时回楼主:
兄弟你悲观了,我找到了一个好办法,就是昨天晚上,universal-imageloader,picasso,包括Fresco,发现他们都是存在内存泄漏,但是可以改,universal-imageloader改了以后就可以了,http://blog.csdn.net/editor19...,找了一个晚上找到的,可以用,其中会有小问题,根据下面的评论和回答就可以搞定
然后楼主把我的答案设置为最佳,但是我发现这个方法相当于把图片加载工具的优点抹杀了,最骚的是
当其他页面尝试使用imageloader加载同样的图片就会发生如下问题,而且并不好解决:
Canvas: trying to use a recycled bitmap android.graphics.Bitmap
我就自己去搞,最终找到一个方法,但是也开始怀疑其他问题,因为在找答案的时候搜到很多内存泄漏的问题,而且图片加载工具肯定很成熟的,怎么可能有这种问题,我就回了楼主:
*再告诉你我的解决方案吧,首先我们之前都是怀疑图片工具的锅,其实我怀疑可能不是,当然我还没有确定,等一下测一下,可能是我们自己的原因导致的内存泄露,导致那个我们重复进去Activity没有被回收,原因是里面一东西没有回收,比如Context,或者Thread,我们用adpter时候最好传getApplication进去,因为我一直在优化,没时间去确认到底是哪里的问题,我现在解决方案,是那个要加载图片的Activity,用ImageLoad来加载,退出的时候之前那个方法回收bitmap,这个Activity以外可能有和这个Activity重复的图片,这样如果外面再用IamageLoad加载图片 ,你程序会崩掉,说你在使用一个已回收的bitmap,所以这时候,这个Activity以外有重复图片的Activity,用Picasso或者其他图片加载工具,这样解决了。这个方法看起来不专业,但能行。但是最重要的是可能我们两个都傻逼了,可能是我们自己的问题导致Activity没有被回收导致的内存泄露,我等一下测一下。我前两天被这个问题折磨,网上找了很久,自己也搞了很久才搞定,只是希望可以帮到更多的人
然后我开始去测试,去掉了之前那个手动回收的方法,发现真的没问题。搞了半天是因为自己因为线程里面传入了当前Activity的Context对象导致销毁Activity的时候线程还没有关,那么将导致Activity的内存资源无法回收,造成内存泄漏。
所以说,大家都没有问题那肯定是自己的问题,这么成熟的框架,不会犯这些错误。我发现imageloader是可以自己回收内存的,缓存达到一个值以后就释放了之前的缓存了。
关于Context:
Context的生命周期是一个Activiy,而ApplicationContext的生命周期是整个程序。我们最要注意的就是Context的内存泄露。在Activiy的UI中要使用Context,而在其他的地方比如数据库、网络、系统服务的需要频繁调用Context的情况时,要使用ApplicationContext,以防止内存泄露。
Android内存泄漏相关文章:http://www.jianshu.com/p/c59c199ca9fa