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

来源:互联网 发布:数据新闻手册 下载 编辑:程序博客网 时间:2024/05/01 13:39

Android性能优化系列之布局优化

Android性能优化系列之内存优化

Android性能优化系列之apk瘦身

应用的启动速度缓慢是我们在开发过程中经常会遇到的问题,比如启动缓慢导致的黑屏,白屏问题,本篇博客就将介绍App启动优化的相关知识。

应用的启动方式

通常来说,启动方式分为两种:冷启动和热启动。

1、冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。冷启动因为系统会重新创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上。

2、热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。热启动因为会从已有的进程中来启动,所以热启动就不会走Application这步了,而是直接走MainActivity(包括一系列的测量、布局、绘制),所以热启动的过程只需要创建和初始化一个MainActivity就行了,而不必创建和初始化Application,因为一个应用从新进程的创建到进程的销毁,Application只会初始化一次。

App的启动过程

本文所指的优化针对冷启动。简单解释一下App的启动过程:

1.点击Launcher,启动程序,通知ActivityManagerService

2.ActivityManagerService通知zygote进程孵化出应用进程,分配内存空间等

3.执行该应用ActivityThread的main()方法

4.应用程序通知ActivityManagerService它已经启动,ActivityManagerService保存一个该应用的代理对象,ActivityManagerService通过它可以控制应用进程

5.ActivityManagerService通知应用进程创建入口的Activity实例,执行它的生命周期

启动过程中Application和入口Activity的生命周期方法按如下顺序调用:

1.Application 构造方法

2.attachBaseContext()

3.onCreate()

4.入口Activity的对象构造

5.setTheme() 设置主题等信息

6.入口Activity的onCreate()

7.入口Activity的onStart()

8.入口Activity的onResume()

9.入口Activity的onAttachToWindow()

10.入口Activity的onWindowFocusChanged()

这里写图片描述

什么才是应用的启动时间

从点击应用的启动图标开始创建出一个新的进程直到我们看到了界面的第一帧,这段时间就是应用的启动时间。

我们要测量的也就是这段时间,测量这段时间可以通过adb shell命令的方式进行测量,这种方法测量的最为精确,命令为:

adb shell am start -W [PackageName]/[PackageName.MainActivity]

1、ThisTime:一般和TotalTime时间一样,除非在应用启动时开了一个透明的Activity预先处理一些事再显示出主Activity,这样将比TotalTime小。
2、TotalTime:应用的启动时间,包括创建进程+Application初始化+Activity初始化到界面显示。
3、WaitTime:一般比TotalTime大点,包括系统影响的耗时。

利用TraceView分析启动时间

在onCreate开始和结尾打上trace.

Debug.startMethodTracing("TestApp");...Debug.stopMethodTracing();

运行程序, 会在sdcard上生成一个”TestApp.trace”的文件.
注意: 需要给程序加上写存储的权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

通过adb pull将其导出到本地

adb pull /sdcard/TestApp.trace ~/testSpeed.trace

打开DDMS分析trace文件,会出现以下的界面
这里写图片描述

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

如何减少应用启动时的耗时

针对冷启动时候的一些耗时,可以采取以下策略:

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

遵循上面三种策略可明显提高app启动速度。

优化应用启动时的体验

对于应用的启动时间,只能是尽量的避免一些耗时的、非必要的操作在主线程中,这样相对可以缩减一部分启动的耗时,另外一方面在等待第一帧显示的时间里,可以加入一些配置以增加体验,比如加入Activity的background,这个背景会在显示第一帧前提前显示在界面上。 对于应用的启动时间,只能是尽量的避免一些耗时的、非必要的操作在主线程中,这样相对可以缩减一部分启动的耗时,另外一方面在等待第一帧显示的时间里,可以加入一些配置以增加体验,比如加入Activity的background,这个背景会在显示第一帧前提前显示在界面上。

方案1:

1、先为主界面单独写一个主题style,设置一张待显示的图片,这里我设置了一个颜色,然后在manifest中设置给MainActivity:

<style name="AppTheme.Launcher"> <item name="android:windowBackground">@drawable/bule</item></style>//...  <activity   android:name=".MainActivity"   android:label="@string/app_name"   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、然后在MainActivity中加载布局前把AppTheme重新设置给MainActivity:

@Override protected void onCreate(Bundle savedInstanceState) {  setTheme(R.style.AppTheme);  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);} 

这样在启动时会先显示background,然后待界面绘制完成再显示主界面:
这里写图片描述

方案2:通过设置Style
(1)设置背景图Theme
通过设置一张背景图。 当程序启动时,首先显示这张背景图,避免出现黑屏

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">        <item name="android:screenOrientation">portrait</item>        <item name="android:windowBackground">>@mipmap/splash</item>        <item name="android:windowIsTranslucent">true</item>        <item name="android:windowNoTitle">true</item></style>

(2)设置透明Theme
通过把样式设置为透明,程序启动后不会黑屏而是整个透明了,等到界面初始化完才一次性显示出来

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">        <item name="android:windowNoTitle">true</item>        <item name="android:windowBackground">@android:color/transparent</item>        <item name="android:windowIsTranslucent">true</item>        <item name="android:screenOrientation">portrait</item>    </style>

两者对比:
Theme1 程序启动快,界面先显示背景图,然后再刷新其他界面控件。给人刷新不同步感觉。
Theme2 给人程序启动慢感觉,界面一次性刷出来,刷新同步。
(3)修改AndroidManifest.xml

 <application        android:name=".App"        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true">        <activity android:name=".MainActivity"         android:theme="@style/AppTheme">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    //......</application>

参考文献:
http://www.jianshu.com/p/a0e242d57360

6 0