应用启动优化
Android应用程序启动时,可以通过log日志查看其启动时间,启动一个Activity时,会有相应的启动耗时输出比如:ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +951ms
1.1. 预研
建立两个空项目App,packageName不同,分别为com.tw.launchpro1
和com.tw.launchpro2
,只包含一个Activity,通过测试比对其启动时间。
1.1.1. AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
启动时间对比:
06-23 11:14:09.253 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +956ms
06-23 11:14:13.359 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +952ms
06-23 11:14:17.397 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +957ms
06-23 11:14:20.478 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +964ms
06-23 11:14:26.593 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +944ms
06-23 11:14:30.477 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +950ms
两个App的启动时间基本相同。
1.1.2. Activity
修改launchpro2.MainActivity
,使它继承自Activity。
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
启动时间对比:
06-23 11:15:50.018 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +951ms
06-23 11:15:53.812 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +707ms
06-23 11:16:04.844 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +952ms
06-23 11:16:09.812 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +705ms
06-23 11:16:14.044 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +959ms
06-23 11:16:17.936 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +719ms
直接继承自Activity的应用,比继承自AppCompatActivity启动时间更快,大概提速240ms。其启动时间为710ms左右。
1.1.3. OtherApp
直接修改我们的Activity继承自Activity,启动时间降到710ms左右,对比一下其它应用,Zoom和微信:
1003 1171 I ActivityManager: Displayed us.zoom.videomeetings/com.zipow.videobox.LauncherActivity: +527ms
1003 1171 I ActivityManager: Displayed us.zoom.videomeetings/com.zipow.videobox.WelcomeActivity: +215ms
1003 1171 I ActivityManager: Displayed com.tencent.mm/.ui.LauncherUI: +648ms
1003 1171 I ActivityManager: Displayed us.zoom.videomeetings/com.zipow.videobox.LauncherActivity: +386ms
1003 1171 I ActivityManager: Displayed us.zoom.videomeetings/com.zipow.videobox.WelcomeActivity: +147ms
1003 1171 I ActivityManager: Displayed com.tencent.mm/.ui.LauncherUI: +547ms
测试的两次Zoom的启动时间分别为527ms
和386ms
,而微信的启动时间为648ms
和547ms
。我们上面的应用的启动Activity,只设置了一个layout,启动时间居然也比Zoom和微信的启动时间长,是否是Theme设置的问题?
下面的时间为今日头条App的启动时间:
// 有广告页面
06-23 18:36:57.136 1003 1171 I ActivityManager: Displayed com.ss.android.article.news/.activity.SplashBadgeActivity: +1s160ms
06-23 18:37:01.513 1003 1171 I ActivityManager: Displayed com.ss.android.article.news/.activity.MainActivity: +886ms
06-23 18:37:07.117 1003 1171 I ActivityManager: Displayed com.ss.android.article.news/.activity.SplashBadgeActivity: +1s229ms
06-23 18:37:13.223 1003 1171 I ActivityManager: Displayed com.ss.android.article.news/.activity.MainActivity: +902ms
06-23 18:37:22.350 1003 1171 I ActivityManager: Displayed
// 无广告页面
com.ss.android.article.news/.activity.MainActivity: +856ms (total +1s715ms)
06-23 18:37:33.251 1003 1171 I ActivityManager: Displayed com.ss.android.article.news/.activity.MainActivity: +898ms (total +1s781ms)
SplashBadgeActivity是头条App的启动广告页面,该页面的启动时间为1s200ms左右,而主页MainActivity的启动时间大概为900ms。 无广告时,在SplashBadgeActivity中不显示View直接进入到MainActivity页面,总共时间为1.7s左右。
1.1.4. Theme
反编译Zoom.apk,查看它的LauncherActivity的Theme设置。
<application android:icon="@drawable/zm_launcher" android:label="@string/zm_app_name" android:largeHeap="true"
android:name="com.zipow.videobox.ZoomApplication">
<activity android:icon="@drawable/zm_launcher" android:label="@string/zm_app_name"
android:name="com.zipow.videobox.LauncherActivity" android:theme="@style/ZMTheme.Transparent">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
它的theme为ZMTheme.Transparent
,在xml里面查看该theme的配置项:
<style name="ZMTheme" parent="@android:style/Theme">
<item name="android:buttonStyle">@style/ZMButton</item>
// ...
</style>
<style name="ZMTheme.Transparent" parent="@style/ZMTheme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:colorBackgroundCacheHint">@null</item>
</style>
该theme继承自Android原生的Theme,除此之外,添加了windowBackground
,windowFrame
和windowIsTranslucent
。尝试将该theme配置添加到launchpro2.MainActivity
,再对比启动时间:
06-23 11:22:57.882 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +713ms
06-23 11:23:02.770 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +684ms
06-23 11:23:08.874 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +712ms
06-23 11:23:13.269 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +683ms
06-23 11:23:24.831 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +709ms
06-23 11:23:29.992 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +668ms
和没添加该theme的launchpro1.MainActivity1
相比,启动时间似乎少了20ms,但基本可以忽略不记,远未达到Zoom的500ms以内的启动速度。
1.1.5. setContentView()
继续在上面的基础上,修改launchpro2.MainActivity
,在其它onCreate方法中,不调用setContentView设置其它布局,测试其启动时间:
06-23 11:33:51.634 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +708ms
06-23 11:33:55.780 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +610ms
06-23 11:34:00.817 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +699ms
06-23 11:34:06.345 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +614ms
06-23 11:34:11.561 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +713ms
06-23 11:34:17.830 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +610ms
未调用setContentView()
时,启动时间大概在610ms
左右。比有设置的时候降了几十Ms。
1.1.6. DaggerActivity
修改两个工程中的Activity都继承自AppCompatActivity,并在launchpro2.MainActivity
应用中引用dagger框架,使用inject注入,再对比其启动时间:
06-23 14:08:26.406 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +1s97ms
06-23 14:08:32.061 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +968ms
06-23 14:08:41.411 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +1s56ms
06-23 14:08:53.256 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +924ms
06-23 14:09:01.340 1003 1171 I ActivityManager: Displayed com.tw.launchpro2/.MainActivity: +1s76ms
06-23 14:09:06.792 1003 1171 I ActivityManager: Displayed com.tw.launchpro1/.MainActivity: +944ms
使用inject注入的Activity,比未使用的启动时间要多100ms
左右。
猜想:如果在项目中有大量Inject注入配置需要在Application.onCreate()前进行注入,App的启动时间可能会更长。
1.2. 结论
- AppCompatActivity相比Activity,由于其添加了AppTheme样式设计支持它会造成大概240ms的开销。
- Dagger依赖注入组件,如果有大量的Dagger依赖配置,也会导致额外的启动开销。
- setContentView(),在xml避免有大量的View层级嵌套造成解析耗时开销。
- Application.onCreate(),避免在该方法进行大量操作,比如第三方SDK,文件读写等。
adb shell am start -W us.zoom.videomeetings/com.zipow.videobox.LauncherActivity adb shell am start -W com.tw.launchpro1/.MainActivity adb shell am start -W com.tencent.mm/.ui.LauncherUI