Android 内存泄露 案例分析

来源:互联网 发布:最好的手机记账软件 编辑:程序博客网 时间:2024/05/01 13:54

实际开发中发现Android内存泄露问题很容易发生,下面大致是一些常犯的问题,希望大家引以为戒:

 

一、注册广播监听器,忘记反注册。

registerReceiver(mReceiver, intentFilter)

unRegisterReceiver(mReceiver, intentFilter)

这两者出现的位置如下:

onCreate    ------    onDestroy

onResume   ------    onPause

onStart      ------    onStop

千万不要放错哦,不然会有问题。

 

二、其他类型监听器,比如监听电话状态:

android.telephony.TelephonyManager.java中,提供了一个监听电话状态的接口:

public void listen(PhoneStateListener listener, int events) {

Xxxxxx;//

}

这个方法经常北使用,如果你在activity里面使用了这个接口,记得在activity destroy的时候将其反注册啊。

如何反注册呢?是unListen么?不是的,看源码注释:

/* To unregister a listener, pass the listener object and set the

     * events argument to

     * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).

     */

所以你只需要在相应位置再次调用listen接口,将listener这个参数值传递成PhoneStateListener#LISTEN_NONE LISTEN_NONE就可以了。

 

 

三、检查你的acrtivity被应用的情况,主要包括:

1.是否被被Application引用

  Applicationandroid应用中属于长生命周期对象,如果你的activity需要被回收,但是此时却被application引用,那么会导致activity无法被顺利回收了。

2.是否被activity中内部类引用

   普通内部类会持有对外部类对象的引用,如果你的内部类对象在从事一个耗时的操作,这个时候如果想回收外部类对象的话,需要先停止内部类对象正在做的操作。

    静态内部类不会持有对外部类对象的引用,可以解决这个问题。

3.是否有被静态引用

   你是否也写过这种傻傻的事情,在一个类中写上了对一个activity的静态引用,

比如 private static XActivity activity = XActivity.getInstance();

你想想,如果你这么写了,你在退出这个XActivity的时候它可以有效的释放么?

你需要考虑如何先取消这个引用才可以,对吧。

 

四.注意重型对象,即占用内存比较多的对象,比如bitmap对象。这类对象在不用的时候要手动回收。

 

简单总结一下:

Java世界的内存泄露问题基本都是一类:一个对象在需要释放的时候还在被别的对象引用,这个时候就无法顺利释放内存。在android开发中要想避免这个问题,就要避免activity在需要回收内存的时候还在被长生命周期对象引用。

Android中长生命周期对应一般包括:

1.Application对象,不用多说了,只有在kill进程的时候生命周期才会结束。

2.内部类对象。这个问题比较隐蔽,需要注意。

3.Framework层的服务对象,比如你在activity listen注册对telephony层电话监听的时候,电话服务就持有了对你activity的引用,所以你需要在不使用的时候及时进行反注册。

上面提到的引用基本都是强引用,在Java世界中还存在弱引用、软引用。这两个引用页是解决android中内存泄露的有效武器啊,你看android框架源码中大量使用了弱引用。

 

如何分析解决android系统中的内存泄露问题呢?授鱼不如授渔,所以总结出一个定位问题的方法十分的重要。这里推荐一个很好用的工具,MAT,地球人都知道吧,你只需要在eclipse中安装这个插件就可以用了。

怎么调试呢?先确保你的android机器可以debug,debug版本的最好了,不然可以无法调试哦。这样插上你的手机,打开ddms,就可以看到一串进程列表。你想调试哪个进程待会就选择哪个。先把你的应用弄到OOM状态,然后MAT会给你列出Suspect的内存分类,你可以看到每一块内存当前被引用的状态,一般情况都可以直接看出问题点。赶紧动手试试吧,如果你发现是被应用内部对象引用,那就是你的代码写的有问题了,检查下是不是有被长生命周期对象在引用;如果是被framework层引用,那可能是厂商自己的BUG了。呵呵,赶紧给厂商反馈说不定还有奖励呢。


这里面有很多文章,一起学习下吧:

http://www.oschina.net/search?scope=blog&q=内存泄露

0 0
原创粉丝点击