随着手机的运行内存(RAM)越来越大,CPU处理能力越来越强的情况,App的启动速度给用户的印象越来越重要,所以App启动优化也势在必行,下面是我在App优化过程中做的一些笔记。

Android 系统的启动

Android开机执行过程如下图所示:

Android系统开机过程图.jpg
  1. 按下电源时,固化在ROM上的引导芯片代码会开始执行,去加载Bootloader到RAM并开始执行;
  2. Bootloader 会将操作系统拉起来并运行;
  3. Linux Kernel启动开启系统设置,找到文件init.rc启动初始化进程;
  4. init进程初始化和启动属性服务后开启Zygote进程;
  5. Zygote开启创建虚拟机并注册JNI方法,开启SystemServer
  6. SystemServer 启动Binder线程池和SystemServiceManager并启动各种服务, 如ActivityManagerService
  7. AMS(ActivityManagerService)启动Launcher

Launcher启动

adb命令

  1. 查看当前的Activity名称

    adb shell dumpsys activity activities 
    
  2. 查看进程

    adb shell ps
    

Application启动

Launcher源码查看:Android XRef

  1. 当我们点击程序图标时,就会执行Launcher类中的onClick方法并把程序的相关信息传入;

  2. 先获取一个intent--->startActivitySafely(v, intent, tag)--》startActivity(v, intent, tag);-->startActivity(intent)

  3. startActivity的流程如下:

    1563348657531.png

    startActivity会开启一个App进程,ActivityThread.java 作为入口,用attach开启App然后再加载Application和ActivityThread.attach --> mgr.attachApplication(mAppThread),会通过远端进程去回调private void handleBindApplication(AppBindData data)

    private void handleBindApplication(AppBindData data){
       Application app = data.info.makeApplication(创建Application对象
         mInstrumentation.callApplicationOnCreate(app);----》 app.onCreate();
    }                
    

黑白屏问题

<!--白屏-->
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!--黑屏 (在以前的老版本上有效,现在的版本默认使用透明处理了)-->
<style name="AppTheme">

黑白屏的主要原因是我们app启动耗时太长即Application中onCreate方法执行时间太长导致的,目前的我所做的修改有如下2步。

提升用户体验

添加Splash主题,执行Applciation#onCreate()时显示该主题,这样可以快速打开App

  • 在res/values/中修改样式:

    • 在默认的res/values/styles/styles.xml中添加一个splash主题

      <style name="StartSplashTheme" parent="AppTheme">
          <!--设置一张默认的背景图来替代白屏或者黑屏-->
          <item name="android:windowBackground">@drawable/logo_splash</item>
          <item name="android:windowFullscreen">true</item>
          <item name="windowNoTitle">true</item>
          <item name="android:windowContentOverlay">@null</item>
          <item name="android:windowNoTitle">true</item>
      </style>
      
    • 新建res/values/sytles-v21/styles.xml中添加一个splash主题:

      <style name="StartSplashTheme" parent="AppTheme">
          <item name="android:windowBackground">@drawable/logo_splash</item>
          <item name="android:windowFullscreen">true</item>
          <item name="windowNoTitle">true</item>
          <item name="android:windowNoTitle">true</item>
          <item name="android:windowDrawsSystemBarBackgrounds">false</item>
          <item name="android:windowContentOverlay">@null</item>
      </style>
      
    • 新建res/values/sytles-v27/styles.xml中添加一个splash主题:

      <style name="StartSplashTheme" parent="AppTheme">
          <item name="android:windowBackground">@drawable/ic_splash</item>
          <item name="android:windowFullscreen">true</item>
          <item name="windowNoTitle">true</item>
          <item name="android:windowNoTitle">true</item>
          <item name="android:windowContentOverlay">@null</item>
          <item name="android:windowDrawsSystemBarBackgrounds">false</item>
          <item name="android:windowTranslucentNavigation">true</item>
          <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
      </style>
      
  • SplashActivity中设置主题

    AndroidManifest.xml

    <activity
              android:name="com.xx.xx.splash.SplashActivity"
              android:label="@string/app_name"
              android:screenOrientation="portrait"
              <!--设置该主题-->
              android:theme="@style/StartSplashTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    

优化Application#onCreate()中的耗时方法

启动时间查看

4.4 以前可以使用adb命令:

adb shell am start -W com.xx.xx.splash.SplashActivity

4.4 以后版本在Logcat输入Display筛选系统日志,不过滤信息No Filters

采用Trace工具分析代码执行时间

File file = new File(Environment.getExternalStorageDirectory(), "xmh.trace");
Debug.startMethodTracing(file.getAbsolutePath());

/*****************************************************************************/
.........需要检测的代码............
/*****************************************************************************/    
Debug.stopMethodTracing();

将文件拉取,然后在Android Studio中利用 Profile查看。

优化方案

  1. 开启一个优先级低的线程,去处理没有handler相关、不操作UI和对异步要求不高的;
  2. 懒加载, 用到的时候才去初始化,一些常量的初始化可以使用类的静态代码块去处理。