在移動端程序中狡恬,用戶希望的是應用能夠快速打開。啟動時間過長的應用不能滿足這個期望俯萎,并且可能會令用戶失望傲宜。輕則鄙視你,重則直接卸載你的應用夫啊。因此函卒,App打開的速度的快慢是影響用戶體驗的重要因素之一。本篇文章主要為大家分享:啟動方式撇眯、啟動流程中可優(yōu)化的環(huán)節(jié)报嵌、檢測工具、優(yōu)化點及黑白屏這四個問題熊榛。
啟動方式
應用啟動的方式主要有以下三種锚国,每種啟動方式都會影響應用向用戶顯示所需的時間,這三種啟動方式分別是:
冷啟動(優(yōu)化目標)
冷啟動是指應用從頭開始啟動:系統(tǒng)進程在啟動后才創(chuàng)建應用進程玄坦。發(fā)生冷啟動的情況包括應用自設備啟動后或系統(tǒng)終止應用后首次啟動血筑。
溫啟動
在熱啟動中绘沉,系統(tǒng)的所有工作就是將 Activity 帶到前臺。只要應用的所有 Activity 仍駐留在內存中豺总,應用就不必重復執(zhí)行對象初始化车伞、布局加載和繪制。
熱啟動
熱啟動涉及冷啟動期間發(fā)生的一些操作喻喳;同時另玖,它比熱啟動花費更多。有許多潛在的狀態(tài)可以被視為熱啟動表伦。例如:
- 用戶在退出應用程序后重啟應用程序谦去。進程可能不會被銷毀還能繼續(xù)運行,但是應用程序需要執(zhí)行onCreate()需要從頭開始重新創(chuàng)建活動蹦哼。
- 系統(tǒng)從應用程序中釋放內存鳄哭,然后用重新啟動它。進程和Activity需要重新啟動翔怎,但傳遞到 onCreate()
的已保存的實例savedInstanceState對于完成此任務有一定助益窃诉。 - ......
啟動流程中可優(yōu)化的環(huán)節(jié)
啟動流程
APP啟動流程如下:
- 單擊桌面應用程序圖標,啟動程序進程使用BinderIPC發(fā)送到系統(tǒng)_計算機網(wǎng)絡服務器進程發(fā)起開始活動請求赤套;
- system_server進程收到請求后飘痛,服務器進程向zygote進程發(fā)送創(chuàng)建進程的請求;
Zygote進程fork出新的子進程容握,即App進程宣脉; - 應用進程,通過Binder IPC向sytem_server進程發(fā)起attachApplication請求;
- system_server進程收到請求后剔氏,做一系列準備塑猖,然后通過binder IPC向App進程發(fā)送scheduleLaunchActivity請求;
- App進程的binder線程(ApplicationThread)收到請求后谈跛,通過handler向主線程發(fā)送LAUNCH_ACTIVITY消息羊苟;
- 主線程收到Message后,通過反射機制創(chuàng)建目標目標Activity感憾,并回調Activity.onCreate()等方法蜡励。
- 至此,App正式上線阻桅,開始進入Activity生命周期凉倚,執(zhí)行完onCreate/onStart/onResume方法,UI渲染結束后便可以看到App的主界面嫂沉。
所以稽寒,我們能優(yōu)化的階段只有 Application.onCreate() —> Activity.onWindowFocusChanged()
檢測工具
啟動時間檢測
啟動的時間怎樣算是合適的?怎樣一個時間范圍內用戶是感覺流暢的趟章?Android Vitals在您的應用出現(xiàn)以下情況時將其啟動時間視為過長:
- 冷啟動用了 5 秒或更長時間
- 溫啟動用了 2 秒或更長時間
- 熱啟動用了 1.5 秒或更長時間
那APP啟動用了多長時間杏糙? 用什么區(qū)檢測慎王?
Logcat Displayed
在 Android 4.4(API 級別 19)及更高版本中,logcat 包含一個輸出行搔啊,其中包含名為 Displayed 的值柬祠。此值代表從啟動進程到在屏幕上完成對應 Activity 的繪制所用的時間。
adb 命令統(tǒng)計
adb shell am start -S -W [packageName]/[activityName]
C:\Users****>adb shell
generic_x86_arm:/ $ am start -S -W com.miss.misslink/.MainActivity
Stopping: com.miss.misslink
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.miss.misslink/.MainActivity }
Status: ok
LaunchState: COLD
Activity: com.miss.misslink/.MainActivity
TotalTime: 941
WaitTime: 961
Complete
WaitTime:包括前一個應用Activity pause的時間和新應用啟動的時間;
ThisTime:表示一連串啟動Activity的最后一個Activity的啟動耗時劲赠;
TotalTime:表示新應用啟動的耗時锅睛,包括新進程的啟動和Activity的啟動,但不包括前一個應用Activity pause的耗時悲龟。
我們一般只用 TotalTime,可以很清楚的知道APP的啟動時間。那我們如何判斷是哪些方法耗時太多導致APP啟動時間過長呢锨天?
CPU profile
API level >= 26
要在應用啟動過程記錄CPU活動,需要做以下操作
2.勾選 Trace Java Methods(跟蹤 Java 方法:在運行時檢測應用剃毒,以在每個方法調用開始和結束時記錄一個時間戳病袄。系統(tǒng)會收集并比較這些時間戳,以生成方法跟蹤數(shù)據(jù)赘阀,包括時間信息和 CPU 使用率益缠。)
-
依次選擇 Run > Profile,將您的應用部署到搭載 Android 8.0(API 級別 26)或更高版本的設備上
主要分析的地方有3個: Flame Chart基公、 Top Down 幅慌、bottom up。
圖片3.png
API level < 26
對于API低于26的轰豆,我們可以調用 Debug API胰伍,調用起點 Application構造函數(shù)
public class MyApplication extends Application {
public MyApplication() {
// 沒有指定絕對路徑,就是相對路徑酸休,相對 sdcard
Debug.startMethodTracing("miss");
}
}
調用終點 Activity.onWindowFocusChanged()
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Debug.stopMethodTracing();
}
如此一來會在 sdcard 路徑下生成 miss 文件骂租,雙擊打開即可
StrictMode 嚴苛模式
StrictMode是一個開發(fā)人員工具,它可以檢測出我們可能無意中做的事情斑司,并將它們提請我們注意渗饮,以便我們能夠修復它們。StrictMode最常用于捕獲應用程序主線程上的意外磁盤或網(wǎng)絡訪問陡厘。幫助我們讓磁盤和網(wǎng)絡操作遠離主線程抽米,可以使應用程序更加平滑、響應更快
// Application onCreate 中使用
@Override
public void onCreate() {
if (BuildConfig.DEBUG) {
//線程檢測策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads() //讀糙置、寫操作
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.penaltyDeath()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects() //Sqlite對象泄露
.detectLeakedClosableObjects() //未關閉的Closable對象泄露
.penaltyLog() //違規(guī)打印日志
.penaltyDeath() //違規(guī)崩潰
.build());
}
優(yōu)化點
- 合理的使用異步初始化云茸、延遲初始化、懶加載機制谤饭。
- 啟動過程避免耗時操作标捺,如數(shù)據(jù)庫 I/O操作不要放在主線程執(zhí)行懊纳。
- 類加載優(yōu)化:提前異步執(zhí)行類加載。
- 合理使用IdleHandler進行延遲初始化亡容。
- 簡化布局
- 第三方庫有些是有優(yōu)化插件的嗤疯,比如ARouter
黑白屏問題
當系統(tǒng)加載并啟動 App 時,需要耗費相應的時間闺兢,這樣會造成用戶會感覺到當點擊 App 圖標時會有 “延遲” 現(xiàn)象茂缚,為了解決這一問題,Google 的做法是在 App 創(chuàng)建的過程中屋谭,先展示一個空白頁面脚囊,讓用戶體會到點擊圖標之后立馬就有響應。
如果你的application或activity啟動的過程太慢桐磁,導致系統(tǒng)的BackgroundWindow沒有及時被替換悔耘,就會出現(xiàn)啟動時白屏或黑屏的情況(取決于Theme主題是Dark還是Light)。消除啟動時的黑/白屏問題我擂,大部分App都采用自己在Theme中設置背景圖的方式來解決衬以。
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/bg</item>
</style>
<activity
android:name=".activity.SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
然后在Activity的onCreate方法,把Activity設置回原來的主題
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
}
這么做校摩,只是提高啟動的用戶體驗看峻。并不能做到真正的加快啟動速度。
總結:啟動速度優(yōu)化也會涉及到布局優(yōu)化與卡頓優(yōu)化秧耗,包括內存抖動等問題备籽。優(yōu)化是一條持續(xù)的道路,很多時候我們會發(fā)現(xiàn)通過各種檢測手段花費了大量的精力去對代碼進行修改得到的優(yōu)化效果可能并不理想分井。因為優(yōu)化就是一點一滴積累下來的车猬,我們平時在編碼的過程中就需要多注意自己的代碼性能。
到此這篇關于Android Android 應用啟動速度優(yōu)化問題分析的文章就介紹到這了,如果對大家有幫助尺锚,請點贊收藏珠闰,謝謝支持!