GC
Android Dalvik Heap与原生Java一样,将堆的内存空间分为三个区域,Young Generation,Old Generation, Permanent Generation。最近分配的对象会存放在Young Generation区域,
当这个对象在这个区域停留的时间达到一定程度,它会被移动到Old Generation,最后累积一定时间再移动到Permanent Generation区域。GC发生的时候,所有的线程都是会被暂停的。执行GC所占用的时间,Young Generation中的时间是最短的,Old Generation其次,Permanent Generation最长。GC时会导致线程暂停,导致卡顿.
2017年5月21日Google在新版本的Android O(8.0)中优化了这个问题,在ART中对GC过程做了优化,据说内存分配的效率提高了10倍,GC的效率提高了2-3倍(可见原来效率有多低),不过主要还是优化中断和阻塞的时间,频繁的GC还是会导致卡顿。
产生性能问题可能原因有哪些
1、在ui线程中做了耗时操作,导致ui线程卡顿
在onCreate中操作sharedpreferences,解析下json数据,正确的做法是,将这些操作使用异步封装起来
2、layout过于复杂,无法在16ms完成渲染的问题
View的渲染大概分为“layout”,“measure”“draw”三个阶段,层级复杂,layout,measure可能就用了很多时间,留给draw的时间就可能不够了,自然而然就悲剧了。
3、view过度绘制的问题
view过度绘制的问题可以说是我们在写布局的时候遇到的一个最常见的问题之一,通常发生在一个嵌套的viewgroup中,比如你给他设置了一个不必要的背景。这方面问题的排查不太难,我们可以通过手机设置里面的开发者选项,打开Show GPU Overdraw的选项,轻松发现这些问题,然后尽量往蓝色靠近。
4、同一时间执行的动画过多,导致CPU或者GPU负载过重
这里主要是因为动画一般会频繁变更view的属性,导致displayList失效,而需要重新创建一个新的displayList,如果动画过多,这个开销可想而知。
DisplayList :在Android把XML布局文件转换成GPU能够识别并绘制的对象。这个操作是在DisplayList的帮助下完成的。DisplayList持有所有将要交给GPU绘制到屏幕上的数据信息
5、 gc过多的问题,上面已经讲
6、静态变量,枚举类型
解决性能问题的方法
1、GPU过度绘制,定位过度绘制区域
这里直接在开发者选项,打开Show GPU Overdraw,就可以看到效果,轻松发现哪块需要优化,那么具体如何去优化
2、主线程耗时操作
将这些操作使用异步封装起来
3、对于measure,layout耗时过多的问题
一般这类问题是优于布局过于复杂的原因导致,现在因为有ConstraintLayout,所以,强烈建议使用ConstraintLayout减少布局层级,问题一般得以解决,如果发现还存在性能问题,可以使用traceView观察方法耗时,来定位下具体原因
4、leakcany:内存泄露监测的工具
5、动画优化
这里主要是想说使用硬件加速来做优化,不过要注意,动画做完之后,关闭硬件加速,因为开启硬件加速本身就是一种消耗
代码的建议
1、当界面不可见的时候释放资源
2、尽量避免使用依赖注入框架
很多依赖注入框架是基于反射的原理,虽然可以让代码看起来简洁,但是是有碍性能的,他们会在程序运行的时候需要扫描代码中的注解,并需要花费内存映射到内存中
3、列表滚动时候停止加载网络图片
迅速滑动列表的时候,只要滚动到的地方,就会产生图片请求,这将产生大量的请求工作,既浪费资源而且界面也会卡顿。
4、注意使用wrap_content
不要使用wrap_content,,推荐使用match_parent,或者固定尺寸,因为 在测量过程中,match_parent和固定宽高度对应EXACTLY ,而wrap_content对应AT_MOST,这两者对比AT_MOST耗时较多。
5、节制的使用service
6、尽可能少的使用 枚举,静态变量
枚举:反编译后可知,我们定义的枚举,编译器会将其转换成一个类并继承Enum类,除此之外,编译器还会生成多个枚举类的实例还声明了一个枚举对象的数组,保存了所有的枚举对象。生成的诸多对象,对象数组,远比静态变量占据内存多。
静态变量:静态的内存使用的是栈空间内存,只要静态变量没有被销毁也没有置null,其对象一直被保持引用,也不会被垃圾回收。
网友评论