Android 性能优化之 启动优化

770 阅读4分钟

1.启动界面过度Splash

1.推荐: Android 12 上推出了全新的启动画面 API SplashScreen。同时为了兼容低版本的使用,Jetpack 框架里推出了同名库

优点: 可以实现进场退场动画和控制显示时间

链接:

2.简单:Theme android:windowBackground

<style name="SplashThemeBase.WithBg">    <item name="android:windowBackground">@drawable/ic_splash_bg</item></style>

2.启动性能优化

参考:应用启动时间 | Android 开发者 | Android Developers

1.测定启动时间

1.在 Android 4.4(API 级别 19)及更高版本中,logcat 包含一个输出行,其中包含名为 Displayed 的值。此值代表从启动进程到在屏幕上完成对应 Activity 的绘制所用的时间。经过的时间包括以下事件序列:

  1. 启动进程。
  2. 初始化对象。
  3. 创建并初始化 Activity。
  4. 扩充布局。
  5. 首次绘制应用。

报告的日志行类似于以下示例:

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

2.您也可以使用 ADB Shell Activity Manager 命令运行应用来测量初步显示所用时间。示例如下:

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

Displayed 指标和以前一样出现在 logcat 输出中。您的终端窗口还应显示以下内容:

Starting: Intent
    Activity: com.example.app/.MainActivity
    ThisTime: 2044
    TotalTime: 2044
    WaitTime: 2054
    Complete
    

-c-a 为可选参数,可让您为 intent 指定 <category><action>

3.reportFullyDrawn() 完全显示所用时间

您可以使用 [reportFullyDrawn()](https://developer.android.google.cn/reference/android/app/Activity#reportFullyDrawn()) 方法测量从应用启动到完全显示所有资源和视图层次结构所用的时间。在应用执行延迟加载时,此数据会很有用。在延迟加载中,应用不会阻止窗口的初步绘制,但会异步加载资源并更新视图层次结构。

如果由于延迟加载,应用的初步显示不包括所有资源,您可能会将完全加载和显示所有资源及视图视为单独的指标:例如,您的界面可能已完全加载,并绘制了一些文本,但尚未显示应用必须从网络中获取的图片。

要解决此问题,您可以手动调用 [reportFullyDrawn()](https://developer.android.google.cn/reference/android/app/Activity#reportFullyDrawn()),让系统知道您的 Activity 已完成延迟加载。当您使用此方法时,logcat 显示的值为从创建应用对象到调用 [reportFullyDrawn()](https://developer.android.google.cn/reference/android/app/Activity#reportFullyDrawn()) 时所用的时间。以下是 logcat 输出的示例:

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

logcat 输出有时包含 total 时间,如初步显示所用时间中所述。

2.可能出现的问题

1.Application.onCreate()

运行 CPU 性能剖析器显示,[callApplicationOnCreate()](https://developer.android.google.cn/reference/android/app/Instrumentation#callApplicationOnCreate(android.app.Application)) 方法最终调用您的 com.example.customApplication.onCreate 方法。如果该工具显示这些方法需要很长时间才能完成执行,您应该进一步探索以查看正在进行哪些工作。

使用内嵌跟踪记录调查可能的问题根源,包括:

  • 应用的初始 [onCreate()](https://developer.android.google.cn/reference/android/app/Application#onCreate()) 函数。
  • 应用初始化的任何全局单例对象。
  • 在瓶颈期间可能发生的任何磁盘 I/O、反序列化或紧密循环。

解决方案:

延迟初始化对象:仅初始化立即需要的对象。例如,不创建全局静态对象,而是转为单例模式,其中应用仅在第一次访问对象时初始化它们。

2.Activity.onCreate

创建 Activity 通常需要进行大量的高开销工作。通常有机会优化这项工作以实现性能改进。

此类常见问题包括: 

  •  扩充大型或复杂的布局。 

  • 阻止磁盘上的屏幕绘制或网络 I/O。 

  • 加载和解码位图。 

  • 栅格化 VectorDrawable (矢量图)对象。 

  • 初始化 Activity 的其他子系统。

通过Jetpack App Startup开发库,我们可以直接高效地在应用启动时初始化组件。开发库和应用的开发者都可以使用此库来简化启动流程,并明确地设置初始化顺序。您可以使用此库设置在启动期间的什么时刻加载哪些组件。

但是App Startup 没有异步加载, 可以用第三方库 Android Startup

影响应用启动的一个典型问题是在初始化时做了太多工作。比如,填充过大或复杂的布局、阻止屏幕绘制、加载和解码位图、垃圾回收等。

  • 1、在Application的构造器方法、attachBaseContext()、onCreate()方法中不要进行耗时操作的初始化,一些数据预取放在异步线程中,可以采取Callable实现。
  • 2、对于sp的初始化,因为sp的特性在初始化时候会对数据全部读出来存在内存中,所以这个初始化放在主线程中不合适,反而会延迟应用的启动速度,对于这个还是需要放在异步线程中处理。
  • 3、对于MainActivity,由于在获取到第一帧前,需要对contentView进行测量布局绘制操作,尽量减少布局的层次,考虑StubView的延迟加载策略,当然在onCreate、onStart、onResume方法中避免做耗时操作。