Android 内存泄漏 总结

什么是内存泄漏?

Android 编程所使用的 Java 是一门使用垃圾收集器(GC, garbage collection)来自动管理内存的语言,它使得我们不再需要手动调用代码来进行内存回收。那么它是如何判断的呢?简单说,如果一个对象,从它的根节点开始不可达的话,那么这个对象就是没有引用的了,是会被垃圾收集器回收的,其中,所谓的 “根节点” 往往是一个线程,比如主线程。因此,如果一个对象从它的根节点开始是可达的有引用的,但实际上它已经没有再使用了(或者说重要性已经很低),是无用的,这样的对象就是内存泄漏的对象;

例子:
1:非静态内部类和匿名内部类造成内存泄漏

private Handler mHandler = new Handler() {
    @Override public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
};

如果此时handler 被传到网络线程,那界面结束后也不能被回收
原因: 网络线程持有 handler,handler 持有整个外部类Activity,导致真个界面的图片等不能被回收!
解决: 使用静态内部类加 WeakReference;

private StaticHandler mHandler = new StaticHandler(this);

public static class StaticHandler extends Handler {
    private final WeakReference<Activity> mActivity;


    public StaticHandler(Activity activity) {
        mActivity = new WeakReference<Activity>(activity);
    }


    @Override public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
}

2:静态变量持有不需要的对象

public class CommUtil {
        private static CommUtil instance;
        private Context context;
        private CommUtil(Context context){
        this.context = context;
        }

        public static CommUtil getInstance(Context mcontext){
        if(instance == null){
            instance = new CommUtil(mcontext);
        }
    //        else{
    //            instance.setContext(mcontext);
    //        }
        return instance;
        }

当调用getInstance时,如果传入的context是Activity的context。只要这个单利没有被释放,那么这个
Activity也不会被释放一直到进程退出才会释放。

解决:
1:使用完后将不再需要的Context置空;
2:尽量使用Applicaticn Context
3:使用 WeakReference 持有 context ;

3:不需要用的监听未移除会发生内存泄露

//例子1:
//        tv.setOnClickListener();//监听执行完回收对象
        //add监听,放到集合里面
        tv.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
            @Override
            public void onWindowFocusChanged(boolean b) {
                //监听view的加载,view加载出来的时候,计算他的宽高等。
                //计算完后,一定要移除这个监听
                tv.getViewTreeObserver().removeOnWindowFocusChangeListener(this);
            }
        });

   // 例子2:
       SensorManager sensorManager = getSystemService(SENSOR_SERVICE);
       Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
        sensorManager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST);
        //不需要用的时候记得移除监听
        sensorManager.unregisterListener(listener);

解决:及时移除监听,网络加载监听一般框架会用WeakReference 持有

4.资源未关闭引起的内存泄露情况
比如:BroadCastReceiver、Cursor、Bitmap、IO流、自定义属性attributeattr.recycle()回收

解决:当不需要使用的时候,要记得及时释放资源。否则就会内存泄露。

5.无限循环动画
没有在onDestroy中停止动画,否则Activity就会变成泄露对象。
比如:轮播图效果。

内存泄漏检测:
1:Android Monitors的内存分析
最直观的看内存增长情况,对比动作操作前GC后内存跟动作操作后GC内存知道该动作是否发生内存泄露。
2:MAT 工具分析
3:Square 公司开源的 LeakCanary 方案 (使用待续…)

猜你喜欢

转载自blog.csdn.net/lqb3732842/article/details/54949588
今日推荐