【安卓开发艺术探索】第15章 性能优化、内存泄漏 笔记

摘要

这一章列举了一些常见的优化方向:

  • 布局优化(在不增加嵌套的前提下用效率更高的ViewGroup,如LinearLayout,FrameLayout)
  • 绘制优化(避免创建对象,避免耗时)
  • 内存泄漏优化(重点,后面阐述)
  • 响应速度优化(ANR)
  • ListView和Bitmap优化(convertView+ViewHolder+滑动时不进行加载的策略,BitmapFactor.Optiond的inSampleSize策略)
  • 线程优化(线程池策略)

下面重点记一些内存泄漏上的知识点。

内存泄漏概念

先看这张图:
内存泄漏
虚拟机会自动回收一部分没有引用的内存资源,但还有一部分不用的资源需要回收,却依然被其他形式引用着,这种情况导致了虚拟机的垃圾回收器不能自动回收,最终使得内存资源越发紧张,甚至导致了内存溢出(OOM)。因此,内存溢出和内存泄漏是不同的概念,同时内存泄漏是内存溢出的原因之一。

内存泄漏原因

参考链接:http://blog.csdn.net/qq_32969313/article/details/51669211
结合上面链接整理如下:

1、集合类

比如一个静态的Map持续地添加其他对象的引用,并不加以删除,导致集合的内存只增不减,没有进行有效回收。

Vector v = new Vector(10);
for (int i = 1; i < 100; i++) {
    Object o = new Object();
    v.add(o);
    o = null;
}

在这个例子中,我们循环申请Object对象,并将所申请的对象放入一个 Vector 中,如果我们仅仅释放引用本身,
那么 Vector 仍然引用该对象,所以这个对象对 GC 来说是不可回收的。
因此,如果对象加入到Vector 后,还必须从 Vector 中删除,最简单的方法就是将 Vector 对象设置为 null。

2、单例模式

不正确使用单例模式是引起内存泄漏的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被JVM正常回收,导致内存泄漏。 如果需要Context,尽量引用Application,而不用Activity。

3、Android组件或特殊集合对象的使用

BroadcastReceiver,ContentObserver,FileObserver,Cursor,Callback等在Activity onDestory或者某类生命周期结束之后一定要unregister或者close掉,否则这个Activity类会被system强引用,不会被内存回收。不要直接对Activity进行直接引用作为成员变量,如果不得不这么做,请用private WeakReference mActivity来做,相同的,对于Service等其他有自己生命周期的对象来说,直接引用都需要谨慎考虑是否会存在内存泄漏的可能。

4、Handler

主要因为如果是以内部类形式创建的Handler,会持有外部类对象的引用(Context或Activity),所以当此Activity结束时,Handler仍然持有Activity的引用,使虚拟机垃圾回收器不能正确回收导致。
解决方法是使用静态内部类,这样不会持有外部类对象的引用,但如果需要访问外部类对象,则使用弱引用WeakReference即可(弱引用会在垃圾回收时直接被回收,软引用会在即将OOM时才进行回收,强引用只有为null时回收)。

5、HandlerThread、Thread

线程方面有两种原因,一种和上面类似,如果采用了内部类来创建线程,即在子线程持有了外部类对象的引用,而导致activity退出时不能被回收。另一个原因是子线程生命周期不可控,如果不在activity退出时关闭线程或进行处理,则会导致线程中持有的对象继续保持。

6、Bitmap

Bitmap的实现有一部分是使用了jni,而这一层的内存不会受虚拟机垃圾回收控制,所以需要单独调用recycle()后,再赋为null,才可回收。

7、属性动画

如果是无限循环的动画,在Activity结束时没有使用animator.cancel()停止,则此activity仍无法被释放,因为view持有着它而animator持有着view。

综上所述

内存泄漏的原因大抵上就几种:(下面的外部类对象一般指Activity)

  • 内部类持有了外部类对象导致外部类对象在结束时不能被释放的。如Thread、Handler、单例模式等。
    解决起来就是静态内部类+弱引用。
  • 外部类对象无意间被其他对象持有了,比如动画、BroadcastReceiver等。
    解决起来就是调用对应的结束方法。
  • 没有意识到内存释放导致无用内存增长,比如Map中的引用没有进行删除、Bitmap回收。
    解决起来就是该删除的删除、该回收的回收。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值