卡顿:Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染。如果你的某个操作是大于16ms,系统在得到VSYNC信号的时候就无法进行正常的渲染,这样就发生了丢帧即卡顿现象。
ANR:主线程在特定的时间内没有做完特定的事情, 通常在如下两种情况下会弹出ANR对话框:
- 5s内无法响应用户输入事件(例如键盘输入, 触摸屏幕等).
- BroadcastReceiver在10s内无法结束
一、渲染优化
1、减少布局层级-扁平化设计
- 首先应当考虑布局层级最小的方案。
- 布局层级相同时,就应当选取合适的父容器,一般来说,有以下几点经验:
- 选取的优先级为:FrameLayout、不带layout_weight参数的LinearLayout、RelativeLayout,这里选取的标准为带有layout_weight的LinearLayout或者RelativeLayout会测量两次。
- 当使用LinearLayout时,应当尽量避免使用layout_weight参数。
- 避免使用RelativeLayout嵌套RelativeLayout。
- 如果允许,那么可以使用Google的ConstraintLayout布局。
2、measure、layout、draw 的耗时时间
不要在onMeasure、onLayout、onDraw方法中频繁地创建对象,例如Paint、Path这样的类。
3、过度绘制
设置/辅助功能/开发者选项/
,点击调试GPU
过度绘制选项打开开关之后,可以看到界面当中会出现各种颜色的矩形,这就对应着过度绘制的等级,颜色越深,表明过度绘制越严重。为避免过度绘制,这就要求
- 减少布局层级
- 去掉不必要的背景(windows默认背景以及Layout背景)
- 使用ViewStub代替需要GONE的异常错误页
- 没有用的父布局时指没有背景绘制或者没有大小限制的父布局,这样的布局不会对UI效果产生任何影响,我们可以把没有用的父布局,通过<merge/>标签合并来减少UI的层次
-
通过canvas.clipRect()来 帮助系统识别那些可见的区域
二、内存优化-内存泄露
1.资源对象没关闭
- 数据库Cursor未关闭
-
调用registerReceiver后未调用unregisterReceiver()
-
未关闭InputStream/OutputStream
-
Bitmap使用后未调用recycle()
-
acitivity中timer和TimerTask未在onDestroy()时cancel掉
-
无用集合中的对象未清理
-
acitivity中属性动画未在onDestroy()时cancel掉
-
acitivity中属性动画未在onDestroy()时cancel掉
2.作用域不一样,导致对象不能被垃圾回收器回收
-
不要保留对Context-Activity长时间的引用(对Activity的引用的时候,必须确保拥有和Activity一样的生命周期);
-
使用Context-Application来替代Context-Activity用于创建单例、静态变量等长时间对象。
-
对于引用生命周期不一样的对象,可以用软引用或弱引用SoftReferner WeakReferner,如果你不想控制内部类的生命周期,应避免在Activity中使用非静态的内部类,而应该使用静态的内部类,并在其中创建一个对Activity的弱引用(Handler应该申明为静态对象, 并在其内部类中保存一个对外部类的弱引用)。
3.内存压力过大
-
使用Adapter时,没有使用系统缓存的convertview和viewholder
-
图片资源加载过多,超过内存使用空间,例如Bitmap 的使用
-
使用缓存技术,比如LruCache、DiskLruCache、对象重复并且频繁调用可以考虑对象池