结合KaDa故事谈谈Android 性能优化

本文链接:https://rainmonth.github.io/posts/A190514.html

结合KaDa故事谈谈Android 性能优化

稳,运行要稳

我们的目标,不是没有蛀牙,而是无泄漏,低crash

内存泄漏与溢出

  • 属性动画导致的内存泄漏(归根结底是匿名类持有外部类引用导致的)
  • 第三方支付导致的内存泄漏(几个PayController采用了静态的HashMap做缓存)
  • WebView导致的内存泄漏

降低Crash率

  • NullPointerException保护

  • 系统提供的API关键方法进行try catch保护

  • 第三方库的API关键方法进行 try catch保护

  • (X)RecyclerView使用问题(坑点)

    • 默认动画
    • 下拉刷新
    • onDetachView() 类路径名报名不一样导致找不到
    • 下拉刷新动画造成内存泄漏
    • 不足一屏会出问题

监测指标及工具方法

指标

  • 从启动到MainActivity的内存(天猫精灵)
  • 内存抖动(内存抖动离谱的话,会导致OOM发生)
  • 内存回收(操作一定时间后回到初始页面内存的使用情况(天猫精灵))

工具方法

  • 用我们那锐利的双眼
  • LeakCanary(已经使用)
  • Android Studio Profile的使用
  • adb shell dumpsys 命令(神器)

快,运行要快

让用户体验丝般顺滑

降低ANR

首当其冲的时降低ANR的发生

UI优化

监测工具

  • Android Studio->Tools->Layout Inspector

  • 开发者选项中的Overdraw

  • 开发者选项中的GPU呈现模式分析,或如下命令:

    1
    adb shell dumpsys gfxinfo com.hhdd.kada

布局优化

  • 尽量避免RelativeLayout的使用
    • RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure(区分下weight=0的情况)
    • RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin
  • 选择性使用ViewStub
  • ImageView的中的src在xml中能不设置就不设置,如果可以请动态设置
  • merge和include的使用
  • ConstraintLayout用起来
    • 结合了LinearLayout和RelativeLayout的优点
    • 圆形相对定位
    • 可见性行为约束(不至于View一被设置成Gone这个UI就垮掉)
    • 宽高比约束
    • Chain(实现LinearLayout layout_weight能达到的效果,有过之而无不及)
    • 提供了虚拟视图(为什么叫虚拟视图,自行查看源码)
      • GuideLine,参考线,解决对齐问题神器
      • Barrier,解决对齐问题,特别是一些输入表单
      • Group,顾名思义,对View进行分组,统一设置其可见性(之前需要把他们放在一个ViewGroup中来进行可见性管理,无形中增加了布局层级)

绘制优化

主要是自定义View

主要注意以下两点:

  1. 避免onDraw中局部变量的创建;(onDraw函数执行会比较频繁,会造成内存抖动,内存抖动就加剧了GC的发生,会造成卡顿)
  2. 避免onDraw中循环的使用

Fragment懒加载用起来

目前KaDa故事App主页面好像没有利用Fragment的懒加载,带来的问题(一打开页面,三大模块的网络请求齐头并进),对App的流畅性以及启动内存都有影响

加快启动速度

主要是冷启动的速度,因为与暖启动热启动相比,冷启动的时间确实有点久

利用AnchorTask进行启动优化

冷启动主要分两个部分:

  • 应用的创建(Application)

    1. 加载并启动应用程序
    2. 启动后立即显示应用程序的空白启动窗口
    3. 创建应用程序进程
  • 主Activity的创建:

    1. 启动主线程
    2. 创建主Activity (这里指的是LaunchActivity)
    3. 加载布局
    4. 屏幕布局
    5. 执行初始绘制
    6. 应用程序进程完成第一次绘制后,系统进程会交换当前显示的背景窗口,将其替换为主活动

小,身材苗条

包体小百分之五,可能新增就增加百分之五(引用自网络,不知道是不是真的)

apk构成

  • AndroidManifest.xml文件

  • assets目录,里面的资源原封不动的打包到apk的,能压缩压缩

  • .dex文件,降低方法数,有可能减少.dex文件的个数

  • libs,so文件的选择性支持

  • res,无用资源的即时清除,Android Studio ->Refactor->Remove unused resources

  • 混淆配置

    这个过程中涉及到第三方库资源的时候需谨慎删除

降低方法数

方法数查看方法,利用dexCount

  • 减少不必要的第三方库引用
  • 避免重复的功能库引用
  • Android studio ->Analyze 用起来

省,省电、省流量、省心

流量已经很廉价,主要是省电和省心

耗电量过大,可能回导致用户卸载App

  • 需要进行网络请求时,我们需先判断网络当前的状态。
  • 在多网络请求的情况下,最好进行批量处理,尽量避免频繁的间隔网络请求。
  • 在同时有wifi和移动数据的情况下,我们应该直接屏幕移动数据的网络请求,只有当wifi断开时在调用,因为,wifi请求的耗电量远比移动数据的耗电量低的低。
  • 后台任务要尽可能少的唤醒CPU。(比方说,锁屏时,QQ的消息提示行就是唤醒了CPU。但是它的提示只有在你打开锁屏或者进行充电时才会进行提示。)

其他

编写高效代码的两个基本原则(摘自网络):

  1. 不要做你不需要做的工作
  2. 如果可以避免,请不要分配内存