正文
}
}
但是要注意,这个方式需要API19+,所以,这里需要对SDK版本进行判断。
计算启动时间——ADB
通过ADB命令可以统计应用的启动时间,指令如下所示:
➜
~
adb shell am
start
-
W
com
.
xys
.
preferencetest
/
.
MainActivity
Starting
:
Intent
{
act
=
android
.
intent
.
action
.
MAIN
cat
=
[
android
.
intent
.
category
.
LAUNCHER
]
cmp
=
com
.
xys
.
preferencetest
/
.
MainActivity
}
Status
:
ok
Activity
:
com
.
xys
.
preferencetest
/
.
MainActivity
ThisTime
:
1047
TotalTime
:
1047
WaitTime
:
1059
Complete
该指令一共给出了三个时间:
-
ThisTime:最后一个启动的Activity的启动耗时
-
TotalTime:自己的所有Activity的启动耗时
-
WaitTime: ActivityManagerService启动App的Activity时的总时间(包括当前Activity的onPause()和自己Activity的启动)
这三个时间不是很好理解,我们可以把整个过程分解
1.上一个Activity的onPause()——2.系统调用AMS耗时——3.第一个Activity(也许是闪屏页)启动耗时——4.第一个Activity的onPause()耗时——5.第二个Activity启动耗时
那么,ThisTime表示5(最后一个Activity的启动耗时)。TotalTime表示3.4.5总共的耗时(如果启动时只有一个Activity,那么ThisTime与TotalTime应该是一样的)。WaitTime则表示所有的操作耗时,即1.2.3.4.5所有的耗时。
每次给出的时间可能并不一样,而且应用从首次安装启动到后面每次正常启动,时间都会不同,区别于系统是否要分配进程空间。
计算启动时间——Screen Record
通过录屏进行启动的分析,是一个很好的办法,在API21+,Android给我们提供了一个更加方便、准确的方式:
➜
~
adb shell
screenrecord
--
bugreport
/
sdcard
/
test
.
mp4
Android在screenrecord中新增了一个参数——bugreport,那么加了这个参数之后,录制出来的视频,在左上角就会增加一行数字的显示,如图所示。
在视频开始前,会显示设备信息和一些参数:
视频开始后,左上角会有一行数字:
例如图中的:15:31:22.261 f=171(0)
其中,前面的4个数字,就是时间戳,即15点31分22秒261,f=后面的数字是当前的帧数,注意,不是帧率,而是代表当前是第几帧,括号中的数字,代表的是『Dropped frames
count』,即掉帧数。
有了这个东西,再结合视频就可以非常清楚的看见这些信息了。
启动时间的调试
模拟启动延时
在测试的时候,我们可以通过下面的方式来进行启动的延迟模拟:
SystemClock
.
sleep
(
2000
)
或者直接通过:
try
{
Thread
.
sleep
(
2000
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
或者通过:
new
Handler
().
postDelayed
(
new
Runnable
()
{
@Override
public
void
run
()
{
// Delay
}
},
2000
);
这些方案都可以进行启动延迟的模拟。
强制冷启动
在『开发者选项』中的Background Process Limit中设置为No Background Processes
优化点
Static Block
很多代码中的Static Block,都是做一些初始化工作,特别是ContentProvider中在Static Block中初始化一些UriMatcher,这些东西可以做成懒加载模式。
Application
Application是程序的主入口,特别是很多第三方SDK都会需要在Application的onCreate里面做很多初始化操作,不得不说,各种第三方SDK,都特别喜欢这个『兵家必争之地』,再加上自己的一些库的初始化,会让整个Application不堪重负。
优化的方法,无非是通过以下几个方面:
阻塞
阻塞有很多种情况,例如磁盘IO阻塞(读写文件、SharedPerfences)、网络阻塞(现在应该不会了)以及高CPU占用的代码(加解密、渲染、解析等等)。
View层级
见《Android群英传》
耗时方法
通过使用TraceView && Systrace && Method Tracing工具来进行排查,见《Android群英传:神兵利器》
App启动优化的一般过程
-
通过TraceView、Systrace来分析耗时的方法与组件。
-
梳理启动加载的每一个库、组件。
-
将梳理出来的库,按功能和需求进行划分,设计该库的启动时机。
-
与交互沟通,设计启动画面,按前文方法进行优化。
解决方案
Theme
当系统加载一个Activity的时候,onCreate()是一个耗时过程,那么在这个过程中,系统为了让用户能有一个比较好的体验,实际上会先绘制一些初始界面,类似于PlaceHolder。
系统首先会读取当前Activity的Theme,然后根据Theme中的配置来绘制,当Activity加载完毕后,才会替换为真正的界面。所以,Google官方提供的解决方案,就是通过android:windowBackground属性,来进行加载前的配置,同时,这里不仅可以配置颜色,还能配置图片,例如,我们可以使用一个layer-list来作为android:windowBackground要显示的图:
start_window.xml
layer
-
list
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
opacity
=
"opaque"
>
item
android
:
drawable
=
"@android:color/darker_gray"
/>
-
bitmap
android
:
gravity
=
"center"
android
: