android内存优化总结
一、内存优化总结
1、Dalvik & ART
Android在4.4之前一直使用的Dalvik虚拟机作为App的运行VM的, 4.4中引入了ART作为开发者备选, 5.0起正式将ART作为默认VM了
7.0后采用了混合编译
2、每个应用(进程)最大可用内存(dalvik)
adb shell getprop dalvik.vm.heapgrowthlimit
adb shell getprop dalvik.vm.heapsize(设置了android:largeHeap=true后)
3、Generational Heap Memory内存模型的概述
在Android和Java中都存在着一个Generational(读音:[ˌdʒenəˈreɪʃənl])
Heap Memory模型,系统会根据内存中不同的内存数据类型分别执行不同的GC操作。Generational Heap Memory模型主要由:Young Generation(新生代)、Old Generation(旧生代)、Permanent(读音:[ˈpɜ:rmənənt])
Generation三个区域组成,而且这三个区域存在明显的层级关系。所以此模型也可以成为三级Generation的内存模型。
其中Young Generation区域存放的是最近被创建对象,此区域最大的特点就是创建的快,被销毁的也很快。当对象在Young Generation区域停留的时间到达一定程度的时候,它就会被移动到Old Generation区域中,同理,最后他将会被移动到Permanent Generation区域中。
在三级Generation内存模型中,每一个区域的大小都是有固定值的,当进入的对象总大小到达某一级内存区域阀值的时候就会触发GC机制,进行垃圾回收,腾出空间以便其他对象进入。
不仅如此,不同级别的Generation区域GC是需要的时间也是不同的。同等对象数目下,Young Generation GC所需时间最短,Old Generation次之,Permanent Generation 需要的时间最长。当然GC执行的长短也和当前Generation区域中的对象数目有关。遍历查找20000个对象比起遍历50个对象自然是要慢很多的。
4、常用的内存优化方法
1)、ListView和GridView的item缓存
2)、避免布局的多层嵌套,减少过度绘制
在手机开启“设置”->“开发者选项”->"调试GPU过度绘制"
3)、页面背景和图片加载
在布局和代码中设置背景和图片的时候,如果是纯色,尽量使用color;如果是规则图形,尽量使用shape画图;如果稍微复杂点,可以使用9patch图;如果不能使用9patch的情况下,针对几种主流分辨率的机型进行切图。
4)、线程
线程不再需要继续执行的时候要记得及时关闭,开启线程数量不易过多,一般和自己机器内核数一样最好,推荐开启线程的时候,使用线程池。
5)、String/StringBuffer
当有较多的字符创需要拼接的时候,推荐使用StringBuffer
6)、避免内存抖动
- 尽量避免在循环体内创建对象,应该把对象创建移到循环体外。
- 注意自定义View的onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象。
- 当需要大量使用Bitmap的时候,试着把它们缓存在数组中实现复用。
- 对于能够复用的对象,同理可以使用对象池将它们缓存起来。
二、内存泄漏检测常用工具
1、android Monitor/Memory Profiler(android studio 3.0 用的Memory Profiler)
2、DDMS
3、Memory Analyzer Tool (MAT)
4、LeakCanary
三、常出现的内存泄漏点
1、MediaPlayer导致的内存泄漏的问题
MediaPlayer 在执行release时未对源码中的mSubtitleController引用的context 进行释放,造成内存泄漏
@Override
protected void onDestroy() {
super.onDestroy();
ReleasePlayer();
}
/** * 释放播放器资源 */
private void ReleasePlayer() {
if (mPlayer != null) {
mPlayer.stop();
mPlayer.reset();
mPlayer.release();
mPlayer = null;
}
}
2、VideoView导致的内存泄漏的问题
android 6.0以前AudioManager用的Context是当前传入的,当activity finish之后 AudioManager依然保持对它的引用,所以就内存泄漏了,6.0后改用ApplicationContext修复了此问题,动态创建VideoView可解决此问题。
3、handler 导致的内存泄漏
如果handler内持有了activity的引用,在activity finish时 handler内的任务未执行完成,将会出现内存泄漏。
//方法一:可以使用静态内部类+弱引用的方法解决。
private static class MyHandler extends Handler {
private WeakReference<Activity> reference;
public MyHandler(Activity activity) {
reference = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
LeakActivity activity = (LeakActivity) reference.get();
if (activity != null) {
activity.xxxxx();
} else {
Logger.d("activity = null");
}
}}
private final Handler mHandler = new MyHandler(this);
//方法二:在 onDestroy中移除handler消息
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
4、单例导致内存泄露
Activity在调用destory时,单例对象中还在持有此activity的引用,就会造成系统无法回收activity内存,出现内存泄漏。
由于Application 的Context的生命周期和应用一样长,可以使用Application Context解决此问题。
5、静态变量导致内存泄露
比如用静态变量声明一个Dialog 、View 、Activity等,也就是当static声明的对象中包含了当前activity的引用,就可能出现内存泄漏。
public class MainActivity extends Activity{
public static Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
}
}
6、非静态内部类和匿名类导致内存泄露
由于非静态内部类和匿名类隐式持有当前activity的引用,造成了内存泄漏。
7、未取消注册或回调导致内存泄露
比如我们在Activity
中注册广播,如果在Activity
销毁后不取消注册,那么这个刚播会一直存在系统中,同上面所说的非静态内部类一样持有Activity
引用,导致内存泄露。因此注册广播后在Activity
销毁后一定要取消注册。
8、Timer和TimerTask导致内存泄露
TimerTask对象在和Timer的schedule()方法配合使用的时候极容易造成内存泄露。
要在合适的时候进行Cancel
即可,比如在onDestroy中做cancel 操作。
9、集合中的对象未清理造成内存泄露
10、资源未关闭或释放导致内存泄露
对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的代码,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
11、属性动画造成内存泄露
如果在Activity中播放此类动画且没有在 onDestroy中去停止动画,那么动画会一直播放下去,尽管已经无法在界面上看见动画效果了,并且这个时候 Activity的 View会被动画持有,而View又持有了Activty,最终Activity无法释放。下面的动画是无限动画,会泄露当前的Activity,解决方法是在Activity的onDestroy中调用animator.cancel()来停止动画。
12、WebView造成内存泄露
1)为加载WebView的界面开启新进程,在该页面退出之后关闭这个进程。
2)在onDestroy方法中执行(待验证)
参考:
http://blog.****.net/u011326979/article/details/50748181
http://blog.****.net/huang_rong12/article/details/51628264
https://www.jianshu.com/p/5db05db4f5ab
http://blog.****.net/vshuang/article/details/39647167
https://www.cnblogs.com/purpleraintear/p/6046441.html
http://blog.****.net/qq_23191031/article/details/63685756
https://www.jianshu.com/p/ab4a7e353076