关于android内存泄露那点事

来源:互联网 发布:unity3d 点击物体 编辑:程序博客网 时间:2024/05/19 02:45

  相信大多安卓开发者在面试的时候如果面试官有点技术都会问到内存泄露和内存溢出的知识点,但是很多开发者都对这个不以为然,要么就是说我写的程序从来没遇到过这类问题,要么就是只知道bitmap是内存溢出的最常见原因,这样的问题都解决过等等。。。如果我是面试官那么我会认为你只值7K以下,那么一般要怎样才能回答的全面点呢,相信你认真看了这篇文章后,你就会觉得自己更上一层楼,对于面试官的这类问题也会很从容了

首先内存泄露和内存溢出是什么关系呢?有人说内存泄露不就是内存溢出(OOM)吗?那么我的理解当然不是,内存泄露只是可能引起OOM的一个原因而已,单张超高清的

bitmap直接放到内存也可能直接引起OOM,这时候我们就不能说是内存泄露导致的OOM了,常见的引起OOM的原因大概有以下几种:

  1,bitmap太大或者bitmap用完没有回收   

  2,数据库的cursor没有关闭  

  3,构造adapter时,没有使用缓存contentview

 4,死循环或者递归

那么如果你面试时说出这些在面试官心里应该是打60分左右,因为这些确实是我们最常遇到的问题,解决办法也都很简单,其中bitmap的解决方法网上有大把的文章我就不扒了,怎样才能在面试官心里打90分以上呢?就是你一定要清楚最重要的一点:对象的内存泄露

通常这种泄露是写程序都会遇到的,所以你说你没遇到过其实是你不知道而已,因为这种泄露很少会引起你的程序报错或崩溃,但是它会造成你的程序运行起来占用内存慢慢变大,从而对性能造成影响,通俗点说就是你的对象GC没办法回收,一直有强引用占用着,也许有人会说就是一个对象而已,能占多少内存?一个对象回收不了,那么这个对象里的对象变量都没办法回收,可能达到成百上千个,比如一个ACTIVITY对象泄露很可能就是几M的内存没办法回收,我们来看看下面的例子

public classSaveDate {
private static SaveDate SAVEDATE;
//上下文privateContextcon;
static SharedPreferencessharedPreferences;privateSaveDate(Context con) {
this.con= con;
} /*** * 得到一个单例对象
***/
public staticSaveDate getInstence(Context con) {
if (SAVEDATE==null) {
SAVEDATE = new SaveDate(con);
}
if (sharedPreferences==null) {
sharedPreferences = con.getSharedPreferences("saveDate", Context.MODE_WORLD_WRITEABLE);
}
return SAVEDATE;
}
}

     这是一个简单的sharedPreferences的单例工具类片段,其中需要一个上下文,如果这在某个activity类里调用了这个类SaveDate.getInstence(this)后就会把这个Activity对象传过来,然后一般我们不用这个Activity以后就直接finish了,但是因为一个静态的对象SAVEDATE一直占用着这个Activity对象,所以GC也就无法回收这个对象,那么很显然你这个Activity对象就叫做内存泄露了,怎么样?想想你在程序中有没有这么写过,那么正确的做法是SaveDate.getInstence(this.getApplication())这样调用,因为Aplication对象的是整个应用的上下文,生命周期是最长的不用担心它泄露,所以在能使用getApplication()的地方我们就不要用Activity做上下文,当然也有很多地方时不能传getApplication()的,那我们就要自己去控制这个对象的生命周期了
     这就是为什么我们在安卓开发中要慎用static变量的原因,因为它用起来传递数据等确实方便,但却很容易造成各种问题包括内存泄露,特别是需要上下文的,比如View,fragmeng等等,也不是说就不能用,就是用了就显得你的代码很Low,而且用了static一定要在要在不用以后置为NULL,在这里给大家推荐下EventBus这个框架,用了之后就再也不用费心数据传递或通知之类的问题了,而且用起来真的简单
     androidstudio的android monitor插件可以很清楚的查看我们的项目内存使用情况,图片是我反复进入activity返回再进再返回的内存使用情况,可以看到没有内存泄露的情况下返回以后,内存就会降低14.7M,一点增长都没有
同样在我加了两句代码private static MsgActivity context; context=this;,故意造成第二个Activity对象内存泄露后,同样的动作就没有上面这么规律了
     
     最后如何让你的程序一个泄露的对象都没有呢?那么也给大家推荐一个超好用的库"leakcanary",使用方法也简单,androidstudio下直接引用这个包就行了,这两个都被我纳为常用库
dependencies {    compile 'de.greenrobot:eventbus:2.+'  这个是上面提到的eventbus    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'  调试时会自动用这个    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'  正式打包会自动用这个就是忽略}
   然后再程序的Application 的oncreate方法中初始化LeakCanary.install(this);这样当你的程序有内存泄露时,手机就会受到这样的通知
点开以后是这样
这就是我上面加的的两行代码造成的内存泄露结果,是不是一目了然,好了文章就到这里,感觉自己特别啰嗦,第一次写博客,写给自己,也写给想提高的人,当然如果你是大牛就不用看了
原创作品,码字不易,转载请注明出处


1 0