Android启动性能优化 - Go语言中文社区

Android启动性能优化


一. 了解APP启动内部机制

1.1 三种启动方式:cold,warm,hot

  1. 冷启动:app将从头开始启动
  2. 暖启动
  3. 热启动

暖启动和热启动,系统将一个正在运行的app从后台转为前台。

我们强烈推荐直接优化冷启动。因为这些优化措施同样可以提高暖启动和热启动的性能。

1.2 冷启动过程

相比其它启动方式,优化冷启动并不容易。因为相比其它两种方式,系统和app显然有更多的工作要做。

  1. 冷启动过程介绍:

    1. 第一阶段:

      在冷启动开始后,系统有三个任务要完成:

      1. 加载和启动app
      2. 在启动后立即为app显示空白的启动窗口
      3. 创建app进程
    2. 第二阶段:

      在系统创建app进程后,app进程负责下一阶段的工作,包括:

      1. 创建app对象,即Application
      2. 启动主线程
      3. 创建入口Activity
      4. 加载views
      5. 布置屏幕
      6. 执行初始化绘制
    3. 第三阶段:

      一旦完成初始化绘制,系统进程将用入口Activity界面替换掉当前显示的背景窗口。此时,用户才能使用app。

      下图显示了这个阶段的工作过程:
      image

  2. 一般来说,性能问题常常发生在创建Application和Activity这两个部分。

    1. 如果app继承了Application并重写了onCreate,请确保里面不要做太多的事情。
    2. 当app进程创建activity时,流程如下:

      1. 初始化属性
      2. 调用构造方法
      3. 调用相应的生命周期方法

      onCreate()方法对启动时间的影响最大,因为它将执行最重要的工作:
      加载views,以及初始化一些将要用到的对象。

1.3 热启动

热启动过程非常简单,其开销比冷启动要少的多:系统仅仅是把app的activity带回到前台。

如果app的activitys仍然保存在内存中,app将不会重新初始化对象、重新布局以及重新绘制。

如果因为内存整理导致部分内存清除,比如调用了onTrimMemory(), 被清楚的对象就需要重新创建。

热启动与冷启动有一个共同的过程:系统进程将显示空白屏幕,直到activity绘制完成。

1.4 暖启动

暖启动的一些过程是冷启动中也有的。有些操作会发生暖启动,比如:
- 用户退出了app,但随即又启动了app。此时app进程可能还在运行,但application和activity必须从onCreate从新启动。
- 系统从内存中清除了app,但用户恰好又启动了app。系统进程和activity需要重新启动,但有些数据内容可能在onCreate中已经被保存到bundle中。这个过程可以参考onSaveInstanceStateonRestoreInstanceState的使用。

二. 启动问题的检测与诊断

2.1 使用Android Vitals

如果app的统计数据满足以下条件,Android Vitals就会认为启动时间过长:
- 冷启动:超过5s
- 暖启动:超过2s
- 热启动:超过1.5s

2.2 诊断

  1. 初始显示花费的时间

    从Android 4.4开始,logcat日志会包含一个Displayed的值。该值代表了从启动app进程到activity绘制完成时的时间值。这个时间包含了下面几个部分:

    1. 启动进程
    2. 初始化对象
    3. 创建并初始化activity
    4. 加载布局
    5. 第一次绘制app

    这个日志的形式如下:

    ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms

    如果Android Studio的Logcat看不到,请尝试禁用日志过滤器。

    有时这条日志会显示total时间:

    ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)

    total时间可能包含另一个已启动但并没有在屏幕显示的activity的时间。只有在单个Activity和total时间存在差异时,才显示total时间。

    你还可以使用adb来追踪,比如:

    adb [-d|-e|-s <serialNumber>] shell am start -S -W
    com.example.app/.MainActivity
    -c android.intent.category.LAUNCHER
    -a android.intent.action.MAIN

    终端显示如下:

    Starting: Intent
    Activity: com.example.app/.MainActivity
    ThisTime: 2044
    TotalTime: 2044
    WaitTime: 2054
    Complete
  2. 完全显示花费的时间

    • Lazy load
      可以使用reportFullyDrawn()方法来测量application启动和所有资源和View层次完整显示之间的时间。

      这在应用程序执行lazy load 的情况下可能有用。

      在lazy load中,app不会阻塞window的初始绘制,而是异步加载资源并更新View层次。

      由于lazy load,app的初始显示不包括所有资源, 可以考虑将加载和显示所有资源和view分开来测量。比如,UI可能加载完成,其中包含文本内容,但需要从网络上的图片还没有显示出来。

    • reportFullyDrawn()
      手动调用该方法,系统就会知道activity是lazy load方式加载。

      logcat的相关输出是这样:

      system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms

      这条日志有时也会包括total时间。

  3. 查找性能瓶颈

    • 使用Android Studio的Method Tracer工具
    • 使用Systrace工具

三. 一些常见的问题

3.1 app初始化任务太多

如果使用自定义的Application类,不要在初始化时做太多的事情。

  1. 诊断:
    • 使用Method tracing
    • 使用Inline tracing(Systrace)
    • 诊断重点如下:
      • application的onCreate方法
      • app初始化的任何全局单例对象
      • 磁盘I/O操作、反序列化、或密集的循环
  2. 优化方案
    尽量使用懒汉式加载。

    • 只初始化立即需要的对象。

      例如,不要创建全局static对象,而是使用懒汉式加载方式的单例

    • 考虑使用诸如Dagger之类的依赖注入框架。对象和依赖关系只有在第一次注入时才会被创建。

3.2 activity初始化任务太多

  1. 常见问题:

    • 加载太深层次或太过复杂的布局
    • 磁盘IO或网络操作
    • 加载和解析图片
    • 栅格化矢量图片对象
    • 初始化activity其它子组件/对象

    诊断方法与application初始化诊断类似

  2. 优化方案

    • 降低布局层次深度:
      • 通过减少重复或嵌套Layout,使整体布局扁平化
      • 在启动时不需要显示的UI,使用ViewStub组件来代替。等启动完成后,在真正需要显示时才会真正加载。
    • 不要一次性初始化所有的资源
      • 将初始化所有资源放在子线程中,以懒汉方式来加载
      • 先加载UI,一些图片或其它资源稍后以异步方式来加载

3.3 启动时主题

  1. 启动时白屏或黑屏问题
    在手机中点击应用程序的图标到应用程序显示完MainActivity的视图这个过程中,通常会用一到两秒的时间。

    在默认activity的主题下(Light or Black),这两秒屏幕就会出现白屏(Light)或者黑屏(Black)。

    实际上是activity默认的主题中的android:windowBackground为白色或者黑色导致的。

  2. 解决白屏或黑屏:

    1. 为主题设置<item name="android:windowDisablePreview">true</item> 属性,禁用窗口预览。

      这样在Activity显示之前,系统永远不会使用窗口的主题来显示它的预览,这也保证了不会出现白屏或者黑屏。

      缺点很明显:启动时间反而会比不禁用窗口预览更多。如果在MainActivity启动过程稍微变慢一点,就会出现点击app图标后,过两秒才会打开 app这样的卡顿效果。

    2. 设置android:windowIsTranslucent属性

      启动时会有半透明效果,缺点同上。

    3. 设置android:windowBackground属性

      <item name="android:windowBackground">@drawable/launch_bg</item>

      直接设置一张背景图片,启动后直接显示图片,而不是黑屏或白屏。此外,这种方法有比较好的用户体验:点击app后,屏幕立刻有了响应。

      建议使用9patch格式的图片,防止全屏显示的时候被拉伸变形。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/cangely/article/details/80809264
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 03:56:41
  • 阅读 ( 692 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢