App 启动优化

本文介绍APP启动速度慢的原因,并提供启动优化方案,如修改主题、避免密集初始化等,还介绍了如何使用ADB、TraceView等工具进行启动耗时分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

personal

许多应用都出现启动速度缓慢,出现黑屏,白屏问题,这是因为 APP 没有进行启动优化。


Google文档

先看看 Google 官方文档 Launch-Time Performance 对应用启动优化的概述:

应用的启动分为冷启动、热启动、温启动,而启动最慢的就是冷启动。

应用在冷启动之时,要执行三个任务:

  1. 加载启动 App;
  2. App 启动时立即展示出一个 Preview Window(预览窗口);
  3. 创建 App 的进程;


而这三个任务执行完毕之后,马上执行以下任务:

  1. 创建 Application 对象;
  2. 创建启动 Activity 对象;
  3. 加载 View;
  4. 布置屏幕;
  5. 进行初始绘制;

而一旦 App 进程完成了第一次绘制,系统进程就会用 Activity 替换已经展示的 Background Window,此时用户就可以使用 App 了。

有上述 APP 启动过程可知,App 进程的创建等环节我们是无法控制的,可以优化的也就是Application、Activity创建以及回调等过程


Google 也给出了优化启动速度的方式:

  1. 修改 Launcher Activity 主题,提前展示预览画面;
  2. 避免在启动时做密集沉重的初始化;
  3. 定位问题:避免I/O操作、反序列化、网络操作、布局嵌套等。

上面三种方式,第一种是用户体验上的提升,第二三种是真实的优化启动速度。


修改主题

App 一般都会有一个 Splash Activity,也就是 APP 启动时的第一个页面,其作用一般是检查更新,初始化程序,宣传公司品牌,以及活动展示。

我们的优化点,就是修改这个 Activity 的 windowBackground 属性,因为如果不指定,系统默认 windowBackground 要么全白要么全黑,导致刚刚启动 APP 时,总能在一瞬间看到这个窗口,体验很差。

具体操作如下:

首先,在 AndroidManifest.xml 中更改 Splash Activity 的主题

     <activity
            android:name=".mvp.ui.activity.SplashActivity"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

然后,在 styles.xml 中指定 windowBackground

    <style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowBackground">@drawable/splash</item>
    </style>

splash.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 背景颜色 -->
    <item android:drawable="@color/white"/>

    <item>
        <!-- 图片 -->
        <bitmap
            android:gravity="center"
            android:src="@drawable/ic_launcher"/>
    </item>
</layer-list>

这种方式其实并没有真正的加速启动过程,而是通过交互体验来优化了展示的效果。


启动加速

现在,我们来真正的加速 APP 的启动,这里关注的就是 Application 以及 Splash Activity 中的初始化代码。

在 Application 中,如果使用了 MultiDex ,那么需要进行对应优化,详情请查看底部参考文章。

其次,在 onCreate() 中,第三方 SDK 会要求在此初始化,如果全部放在主线程,这样的方式肯定是过重的。

解决办法是:异步加载、延时加载、懒加载。

将耗时操作放到子线程,争抢资源的操作进行延时加载或者懒加载。

具体使用哪种方式,这还要根据 第三方SDK 自身情况来决定,这里也不易展开。

我们知道,最常见的解决办法是异步加载,启动时,耗时操作发生在主线程,那是不是多开几个子线程同时操作就行呢?不是。

优化启动不能全都靠着异步来解决问题,错误的使用线程不仅不能改善,反而肯能加剧卡顿。是否需要开启线程?需要开几个线程?这些需要根据具体情况分析性能瓶颈后,才能给出对应的解决方式。

开启线程的方式也同样有区别,Thread、ThreadPool、AsyncTask、HandlerThread、IntentService都各有利弊。分析可知,IntentService 运行在子线程,而且还可以与 Activity 绑定,所以一般会使用 IntentService 来进行一些可以异步的初始化工作。

除了异步,还应该多多考虑,一些初始化是否可以使用延时加载,是否能使用懒加载?

还有一些流程性的事物也可以优化,比如 广告页的下载展示,APP 后台下载升级等。


工具的使用

在优化启动时,我们必须掌握一些分析耗时的基础工具。

1. 使用 ADB

最简单的方式是通过 ADB 查看启动耗时

adb shell am start -W packagename/activity

例如:

➜ adb shell am start -W com.medprin.medprin/com.medprin.medprin.mvp.ui.activity.SplashActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.medprin.medprin/.mvp.ui.activity.SplashActivity }
Status: ok
Activity: com.medprin.medprin/.mvp.ui.activity.SplashActivity
ThisTime: 248
TotalTime: 248
WaitTime: 250
Complete

这里解释一下三个值的含义:

  • WaitTime 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;
  • ThisTime 表示一连串启动 Activity 的最后一个 Activity 的启动耗时;
  • TotalTime 表示新应用启动的耗时,包括新进程的启动和 Activity 的启动。

详细解释,请看Android 中如何计算 App 的启动时间?


如果关心系统启动应用耗时,参考WaitTime;

如果关心应用有界面Activity启动耗时,参考ThisTime。

如果只关心某个应用自身启动耗时,参考TotalTime,开发者一般关注这个;


2.TraceView

使用 adb 的方式太简单粗略了,只能看出启动的总耗时,也看不出具体哪些地方耗时多长,这个时候就需要更加专业的工具,TraceView。

使用非常简单,直接在想要监测位置的开头和结尾,各自调用两个方法

Debug.startMethodTracing("Test");//开始
...
Debug.stopMethodTracing();//结束

运行程序,会在 sdcard 上生成名为 Test.trace 的文件。注意,sdcard 的操作需要添加权限。

然后通过 adb pull 命令 将文件导入到本地后,使用 DDMS 打开 trace 文件, 或者 直接使用 AS3.0之后出现的工具 Devices File Exploer ,直接打开 trace 文件。

一般只需要关注两个值:

  • Cpu Time / Call:反映调用次数不多,但每次调用却需要花费很长时间的函数
  • Calls + Recur Calls / Total:反映自身占用时间不长,但调用却非常频繁的函数


3. Hugo

还有一个是 JakeWharton 的 hugo ,这个库利用 AspectJ 使用注解,可以非常方便的打印方法耗时。

就像这样:

@DebugLog
public String getName(String first, String last) {
  SystemClock.sleep(15); // Don't ever really do this!
  return first + " " + last;
}
V/Example: ⇢ getName(first="Jake", last="Wharton")
V/Example: ⇠ getName [16ms] = "Jake Wharton"

详细集成配置,请查看 GitHub 上文档


参考

Android性能优化(一)之启动加速35%

Android性能优化系列之App启动优化

APP启动优化

Android的几种多线程方式

TraceView 简介及其案例实战

使用 TraceView 找到卡顿的元凶

启动速度优化之耗时检测处理

美团Android DEX自动拆包及动态加载简介

Android MultiDex初次启动APP优化

其实你不知道MultiDex到底有多坑


一、综合实战—使用极轴追踪方式绘制信号灯 实战目标:利用对象捕捉追踪和极轴追踪功能创建信号灯图形 技术要点:结合两种追踪方式实现精确绘图,适用于工程制图中需要精确定位的场景 1. 切换至AutoCAD 操作步骤: 启动AutoCAD 2016软件 打开随书光盘中的素材文件 确认工作空间为"草图与注释"模式 2. 绘图设置 1)草图设置对话框 打开方式:通过"工具→绘图设置"菜单命令 功能定位:该对话框包含捕捉、追踪等核心绘图辅助功能设置 2)对象捕捉设置 关键配置: 启用对象捕捉(F3快捷键) 启用对象捕捉追踪(F11快捷键) 勾选端点、中心、圆心、象限点等常用捕捉模式 追踪原理:命令执行时悬停光标可显示追踪矢量,再次悬停可停止追踪 3)极轴追踪设置 参数设置: 启用极轴追踪功能 设置角度增量为45度 确认后退出对话框 3. 绘制信号灯 1)绘制圆形 执行命令:"绘图→圆→圆心、半径"命令 绘制过程: 使用对象捕捉追踪定位矩形中心作为圆心 输入半径值30并按Enter确认 通过象限点捕捉确保圆形位置准确 2)绘制直线 操作要点: 选择"绘图→直线"命令 捕捉矩形上边中点作为起点 捕捉圆的上象限点作为终点 按Enter结束当前直线命令 重复技巧: 按Enter可重复最近使用的直线命令 通过圆心捕捉和极轴追踪绘制放射状直线 最终形成完整的信号灯指示图案 3)完成绘制 验证要点: 检查所有直线是否准确连接圆心和象限点 确认极轴追踪的45度增量是否体现 保存绘图文件(快捷键Ctrl+S)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值