【性能优化】App启动优化与耗时定位

1,318 阅读4分钟

App启动流程

1. App启动的整个过程,可以分解成下面几个过程:

  • 用户在Launcher上点击App Icon

  • 系统为App创建进程,显示启动窗口

  • App在进程中创建自己的组件

    这个过程可以用下面这幅图来描述:

而我们能够优化的,也就是下面Application的创建部分,系统的进程分配以及一些窗口切换的动画效果等,都是跟ROM相关的,我们无法处理。所以,我们需要把重点放到Application的创建过程。

2. 起始终止点,获取总启动时间的方法:

  • 查看Logcat

在 Android Studio Logcat 过滤关键字 “Displayed”, 可以查看到如下日志:2020-10-11 10:27:15.198 1254-1326/? I/ActivityTaskManager: Displayed com.armrest.application/.MainActivity: +685ms后面的+685ms就是冷启动耗时

  • adb dump

通过终端执行“adb shell am start -W -S <包名/完整类名> ” “TotalTime:685”即为本次冷启动耗时(单位ms)

 C:\1_FTD_E\Task_handrail\armrest-app-0925>adb shell am start -W -S com.armrest.application/com.armrest.application.ui.main.SplashActivity
Stopping: com.armrest.application
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.armrest.application/.ui.main.SplashActivity }
Status: ok
LaunchState: COLD
Activity: com.armrest.application/.MainActivity
TotalTime: 685
WaitTime: 686
Complete

另外,使用adb shell ps -A | grep "包名",可以查询进程号,adb shell kill -9 xxxx(xxxx为进程号可以杀掉应用进程,重新测试启动时间) image.png

3. 定位耗时的方法:

获取耗时函数的方法有2种:

  • 自动开始记录 CPU 活动,请执行以下操作:

依次选择 Run > Edit Configurations。 image.png 在 Profiling 标签中,勾选 Start recording a method trace on startup 旁边的复选框。 从菜单中选择 CPU 记录配置。

image.png 点击 Apply。 依次选择 Run > Profile,将您的应用部署到搭载 Android 8.0(API 级别 26)或更高版本的设备上。

  • 手动开始记录 CPU 活动,请使用Android os自带的Debug类:

可以在代码中合适的位置,例如 onCreate()onWindowFocusChanged 中,分别添加 android.os.Debug.startMethodTracing()android.os.Debug.stopMethodTracing() 方法来生成 trace 文件,该文件生成在 sdcard 根目录下或者应用的目录中。

4. profile工具使用的个人理解

添加耗时函数,测试效果,如下图:

  • 耗时函数1: image.png

  • 耗时函数2: image.png

  • 整体cpu效果图: image.png

  • 耗时说明 耗时函数耗时3秒:

summary:显示总耗时信息

Top down:展示正向调用的关系,从上带下

Frame chart: 展示倒置的调用图表,同时点击能够跳转到制定的IDE中的响应函数

Bottom up: 展示倒置的调用图表, 显示倒置的函数图 image.png

5.解决方案

  • App release版本,相比debug版本,包括app和使用第三方库release版本的代码压缩和资源优化都会提升启动效率
  • 显示优化,当App没有完全起来时, 屏幕会一直显示一块空白的窗口(一般来说是黑屏或者白屏, 根据App主题). 这种现象带来的用户体验非常差,所以需要启动页做主题优化,启动页加载一个windowBackground的自定义启动页效果让体验更好,常见的启动页广告,微信地球界面都是这种作用。
    <style name="LauncherTheme" parent="AppTheme">
        <item name="android:windowBackground">@drawable/background</item>
    </style>

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
  • 优化生命周期内的非UI行为,比如第三方依赖库和初始化等,常见的比如延迟初始化或者IntentService异步初始化等等,目的和懒加载思路基本一致,不是必须开机立马初始化的可以延迟或者等待用的时候再去初始化更合理,最难得优化也在这部分执行初始化还要保证用的时候是可用,这个是重点
getWindow().getDecorView().post(new Runnable() {

  @Override public void run() {
    ……
  }
});
public class InitIntentService extends IntentService {

    private static final String ACTION = "com.xys.startperformancedemo.action";

    public InitIntentService() {
        super("InitIntentService");
    }

    public static void start(Context context) {
        Intent intent = new Intent(context, InitIntentService.class);
        intent.setAction(ACTION);
        context.startService(intent);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        SystemClock.sleep(2000);
        Log.d(TAG, "onHandleIntent: ");
    }
 }
  • 资源优化:一个自然是优化布局、布局层级,一个是优化资源,尽可能的精简资源、避免垃圾资源,这些可以通过混淆和tinyPNG这些工具来实现。 大图或者层级过多都会导致UI渲染慢,不能快速的展示给用户

6. 总结

  • Application的onCreate到首屏Activity的onResume不要做太多耗时操作. 能异步的尽量异步去初始化或者执行

ps: 关于Android应用启动慢的偶现问题,可以通过"start U0|am_|wm_"等标签去查启动log am_restart_activity和am_stop_activity能够看出APP切换的时间,细致查一下启动慢的原因,耗时再哪里. 另外,如图am_low_memory出现代表系统内存不足,也会导致应用启动慢。

e8eaf8948e033f77c2a37e46890dbdc.png

7.参考:站在巨人的肩膀上:

cpu详解参考blog.csdn.net/u011578734/…

Profiler使用详解blog.csdn.net/qq_39577753…

启动优化参考www.jianshu.com/p/cdc07a7be…