一、稳定性优化
在Android应用开发中,影响稳定性的原因很多,比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等,都会对应用的稳定性造成影响。其中最常见的两个场景是:Crash 和 ANR,这两个错误将会使得程序无法使用。
1、内存泄露
当程序不再使用该内存,但这块内存没有释放,而产生的无用的内存消耗的时候就是内存泄露。
内存泄露的场景
- 单例的时候Context传的Activity,解决是尽量用MyApplication.getContext()
- 非静态内部类,内部类持有外部类的对象,而这里外部类就是Activity,如果内部类没有被GC掉,Activity就会造成内存泄漏,解决将该内部类设为静态内部类
- 资源没关闭,对于使用了BraodcastReceiver,ContentObserver,File,游标 Cursor,Stream,Bitmap等资源的使用,没有及时关闭或者注销
说明
在开发中,内存泄漏一般情况不会导致app崩溃,但是他们耗尽大量的内存,这样我们GC的工作会更为频繁(因为可真真正正使用的内存减少了),因为GC是一个耗时耗能的操作,所以给我们的只管感受就是页面卡顿。
2、OOM
OOM,全称“Out Of Memory”,意思是“内存用完了”。 它来源于java.lang.OutOfMemoryError。
当堆内存不足或者有多个不同Activity内存泄漏时,app运行一段时间堆内存超过系统规定的最大值 heapSize,就会出现内存溢出(OOM),app崩溃。
OOM的场景
- 图片过大导致 OOM,解决方法,等比例缩小图片,或图片采用软引用,及时地进行 recyle()操作。
- 界面切换导致 OOM,横竖屏切换时尽可能少地重复使用一些代码,比如重复调用数据库,反复使用某些对象等。切换有大图片时避免 xml 的重复加载。
- 查询数据库没有关闭游标
- 构造 Adapter 时,没有使用缓存的 convertView
- Bitmap 对象不再使用时调用 recycle()释放内存
- 内存泄漏时会导致OOM
3、ANR
ANR全名Application Not Responding, 也就是"应用无响应". 当操作在一段时间内系统无法处理时, 系统层面会弹出ANR对话框。
出现ANR的主要原因是主线程(UI线程)里面做了太多的阻塞耗时操作, 例如文件读写, 数据库读写, 网络查询等。
Android系统中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会检测App的响应时间,如果App在特定时间无法相应屏幕触摸或键盘输入时间,或者特定事件没有处理完毕,就会出现ANR。
- Activity出现ANR是超过5秒
- Broadcast出现ANR是超过10秒
- Service出现ANR是超过20秒
- HandleMessage回调函数执行超过10秒
ANR的原因
- IO操作,如数据库、文件、网络
- CPU不足,一般是别的App占用了大量的CPU,导致App无法及时处理
- 硬件操作,如camera
- 线程问题,如主线程被join/sleep,或wait锁等导致超时
- service问题,如service忙导致超时无响应,或service binder的数量达到上限
- system server问题,如WatchDog发现ANR
ANR分析
- 获取ANR产生的trace文件data/anr/traces.txt,查看ANR发生的进程pid, 时间, 以及进程名字(包名).找到代码点, 然后往前推, 看方法调用栈, 追溯到问题产生的根源.
- CPU满负荷导致ANR,CPU占用接近100%, 满负荷了。
- 内存原因有可能会导致ANR,例如如果由于内存泄露, App可使用内存所剩无几, 我们点击按钮启动一个大图片作为背景的activity, 就可能会产生ANR,可以看到free的内存已所剩无几。、
- 除了查看traces.txt外,还可以查看log,或DDMS分析
4、Crash
常见的异常
- NullPointerException 空指针
- ClassCastException 类型转换异常
- IndexOutOfBoundsException 下标越界异常
- ActivityNotFoundException Activity未找到异常
- IllegalStateException 非法状态异常
- ArrayIndexOutOfBoundsException 数组越界异常
- SecurityException 安全异常
二、界面优化
绘制的层级深、页面复杂、刷新不合理,由于这些原因会导致界面卡顿。
优化方式
- 布局复用,使用<include>标签重用layout;
- 提高显示速度,使用<ViewStub>延迟View加载;
- 减少层级,使用<merge>标签替换父级布局,布局复杂的用ConstraintLayout;
- 减少刷新次数,缩小刷新区域
- 动画优化,在实现动画效果时,需要根据不同场景选择合适的动画框架来实现。有些情况下,可以用硬件加速方式来提供流畅度。
三、分析工具
Memory Monitor 工具
Memory Monitor是Android Studio自带的一个内存监视工具,它可以很好地帮助我们进行内存实时分析。通过点击Android Studio右下角的Memory Monitor标签,打开工具可以看见较浅蓝色代表free的内存,而深色的部分代表使用的内存从内存变换的走势图变换,可以判断关于内存的使用状态,例如当内存持续增高时,可能发生内存泄漏;当内存突然减少时,可能发生GC等。
Memory Analyzer工具
MAT 是一个快速,功能丰富的 Java Heap 分析工具,通过分析 Java 进程的内存快照 HPROF 分析,从众多的对象中分析,快速计算出在内存中对象占用的大小,查看哪些对象不能被垃圾收集器回收,并可以通过视图直观地查看可能造成这种结果的对象。
LeakCanary工具
LeakCanary是一个内存监测工具,该工具是Square公司出品的,所谓Square出品必属精品,LeakCanary的官方地址为https://github.com/square/leakcanar,我们可以在Gradle里引用它。
Android Lint 工具
Android Lint 是Android Sutido种集成的一个Android代码提示工具,它可以给布局、代码提供非常强大的帮助。如果在布局文件中写了三层冗余的LinearLayout布局,就会在编辑器右边看到提示。当然这个是一个简单的举例,Lint的功能非常强大,大家应该养成写完代码查看Lint的习惯,这不仅让你及时发现代码种隐藏的一些问题,更能让你养成良好的代码风格,要知道,这些Lint提示可都是Google大牛们汗水合智慧的结晶。
monkey 测试
Monkey是一款app的自动化测试工具,monkey是猴子的意思,所以从原理上说,它的自动化测试就类似猴子一样在软件上乱敲按键,猴子什么都不懂,就爱捣乱。Monkey原理也是类似,通过向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、滑动Trackball、手势输入等操作),来对设备上的程序进行测试,检测程序长时间的稳定性,多久的时间会发生异常。
monkey需要通过adb来唤醒,即通过在cmd窗口中执行: adb shell monkey {+命令参数}来进行Monkey测试。
过度绘制检测
设置 -> 开发者选项 -> 调试GPU过度绘制 -> 显示GPU过度绘制
通过Hierarchy Viewer去检测渲染效率,去除不必要的嵌套
一个app卡顿,用什么工具检测?
1、Traceview卡顿检测, Traceview是Android平台特有的数据采集和分析工具,集成在DDMS工具中,可以采集程序中的方法执行耗时、调用关系、调用次数以及资源占用等情况。
2、BlockCanary是一个Android平台的一个非侵入式的性能监控组件。
blockcanary完美利用了安卓上的消息机制,给Looper设置一个Printer,通过记录堆栈和CPU信息,计算主线程处理消息的时间,如果超过了阈值,就检索此时的堆栈和cpu信息来帮助分析卡顿原因。
OOM 和 ANR 问题怎么排查?
OOM,内存优化(包括内存泄漏)常用的是Memory Profiler,或 MAT 、 LeakCanary
应用卡顿,查看CPU是使用情况,常用的是CPU Profiler,traceview,BlockCanary;
查看布局是否过度绘制,在开发者模式中打开GPU。
参考链接
https://www.jianshu.com/p/f7006ab64da7
https://blog.youkuaiyun.com/xiangzhihong8/article/details/92800490
https://zhuanlan.zhihu.com/p/141203533