Android-性能优化-03-启动优化-APP 启动流程

295 阅读4分钟

1 APP启动流程

image.png

①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起,startActivity请求;

②system_server进程接收到请求后,向zygote进程发送创建进程的请求;

③Zygote进程fork出新的子进程,即App进程;

④App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

⑤system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

⑥App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

⑦主线程在收到Message后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法。

⑧到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面

2 与app开发者有关的阶段总结

image.png

2.1 进程fork阶段

image.png

2.2 Application 的启动阶段

image.png

  • bindApplication

1)ActivityThread.main

2)handleBindApplication

  • attachBaseApplication

1)4.x 之前的multidex加载优化

2)加固热修复导致延迟

  • installProvider

1)开源库中的Provider初始化

2)自己项目的provider初始化

  • application:onCreate

1)优化最大的部分,异步,按需加载,懒加载

2.3 Handle间隙

image.png

监控主线程的相关消息对主线程消息进行优化

2.4 Activity阶段

Activity启动流程

image.png

image.png

Activity显示

image.png

  • Activity onCreate

1)XML文件解析,反射

2)异步并发构建Viewtree

  • View构建

1)将Inflate过程最大异步化

1)View的度量布局和显示

  • View显示

2)层级优化

3)布局优化

2.5 数据的加载

image.png

1)数据预加载

2)数据缓存机制

3)显示数据加载优先级调度

2.6 黑白屏

image.png

1 黑屏原因

  1. 启动时间过长

    • Application 初始化耗时太长。
    • 资源加载阻塞主线程。

protected attachBaseContext(Context base){

}

@Override

public void onCreate(){

    super.onCreate();

    // 这里的逻辑过于复杂,耗时多

}
  1. 第一个activity 的onCreate(),onStart(),onResume() 里面耗时
override fun onCreate() {
    super.onCreate()
// 这里的逻辑过于复杂,耗时多
}

override fun onStart() {
    super.onStart()
// 这里的逻辑过于复杂,耗时多
}

override fun onResume() {
    super.onResume()
// 这里的逻辑过于复杂,耗时多
}

3. Theme 配置问题

*   启动时未设置合适的窗口背景(Window Background)。
*   使用了默认的黑色主题。

2 白屏原因

  1. 默认窗口背景

    • 系统默认的 WindowBackground 主题颜色为白色,启动时未修改。
  2. 首次布局渲染缓慢

    • setContentView 的布局复杂,导致渲染时间过长。
    • 布局加载图片资源或网络资源。

3 解决方案

(1) 设置启动主题背景

通过设置 WindowBackground,避免黑白屏出现。

具体实现:

res/values/styles.xml 中添加启动主题:

xml
复制代码
<style name="AppTheme.Launcher" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- 设置启动背景 -->
    <item name="android:windowBackground">@drawable/splash_screen_background</item>
    <!-- 禁用 ActionBar -->
    <item name="windowActionBar">false</item>
    <item name="android:windowNoTitle">true</item>
</style>
  • 常见配置

    • @drawable/splash_screen_background 可以是简单的颜色或图片资源。
    • 如果需要渐变背景,可以使用 @drawable/gradient_background

AndroidManifest.xml 中将此主题应用于启动 Activity

xml
复制代码
<activity
    android:name=".MainActivity"
    android:theme="@style/AppTheme.Launcher">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

(2) 动态切换主题

Activity 完成初始化后,切换回应用的主主题。

实现方法:

kotlin
复制代码
override fun onCreate(savedInstanceState: Bundle?) {
    // 切换到正常主题
    setTheme(R.style.AppTheme)
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
}

(3) 优化 Application 和 Activity 初始化
  1. 减少初始化操作

    • 将一些不必要的初始化延迟到后台线程。
    • 使用 WorkManagerHandlerThread 处理非关键任务。
  2. 避免阻塞主线程

    • 避免在 onCreate 中执行复杂的逻辑或长时间 IO 操作。
    • 优化 ContentProvider 的加载。
  3. Lazy Load 机制

    • 对资源加载和依赖初始化采用懒加载策略,按需加载。

(4) 简化布局文件
  1. 优化布局结构

    • 避免嵌套过深的 LinearLayout,可以使用 ConstraintLayout 替代。通过Chain等功能,完全可以在一个ConstraintLayout里实现。层级减少,意味着渲染性能提升,官方的数据是渲染速度比RelativeLayout提高大约40%。
    • 使用 ViewStub 对延迟显示的视图进行优化。
  2. 预加载资源

    • 预加载启动必要的图片和字体,避免布局解析等待。

(5) 使用 Splash Screen API

从 Android 12 开始,Google 提供了专用的 Splash Screen API,可用于优雅地显示启动画面。

配置方法:

  1. 添加 SplashScreen 依赖:

    gradle
    复制代码
    implementation "androidx.core:core-splashscreen:1.0.0"
    
  2. AndroidManifest.xml 配置:

    xml
    复制代码
    <activity
        android:name=".MainActivity"
        android:exported="true"
        android:theme="@style/Theme.App.SplashScreen">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
  3. 自定义启动背景: 在 res/values/themes.xml 配置:

    xml
    复制代码
    <style name="Theme.App.SplashScreen" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/splash_background</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash_icon</item>
        <item name="windowSplashScreenIconBackgroundColor">@color/icon_background</item>
        <item name="postSplashScreenTheme">@style/AppTheme</item>
    </style>
    

4. 常见问题排查

  1. 黑屏仍然存在

    • 检查是否未正确设置 windowBackground
    • 确保未执行耗时操作。
  2. 白屏出现时间过长

    • 优化布局文件。
    • 检查图片资源加载时间。
  3. 闪屏后仍有卡顿

    • 优化启动逻辑,减少 onCreate 中的复杂操作。

3 view 显示相关

3.1 activity与 PhoneWindow与DecorView关系

image.png

3.2 View 层级结构

image.png

对应于ViewRootImpl(替代ViewRoot)类,它是连接WindowManager和DecorView的纽带的三大流程均是通过ViewRoot完成的。当Activity对象被创建完毕后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联