Android 應用啟動速度優(yōu)化問題分析

在移動端程序中狡恬,用戶希望的是應用能夠快速打開。啟動時間過長的應用不能滿足這個期望俯萎,并且可能會令用戶失望傲宜。輕則鄙視你,重則直接卸載你的應用夫啊。因此函卒,App打開的速度的快慢是影響用戶體驗的重要因素之一。本篇文章主要為大家分享:啟動方式撇眯、啟動流程中可優(yōu)化的環(huán)節(jié)报嵌、檢測工具、優(yōu)化點及黑白屏這四個問題熊榛。


c2cfb9fac904c460b395730c9a81a588.jpeg

啟動方式

應用啟動的方式主要有以下三種锚国,每種啟動方式都會影響應用向用戶顯示所需的時間,這三種啟動方式分別是:

冷啟動(優(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é)

v2-907a50cad712e85626bb44e17c4adde2_720w.png

啟動流程

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 的繪制所用的時間。


2021110115512165.jpg

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活動,需要做以下操作

1.依次選擇 Run > Edit Configurations
圖片2.png

2.勾選 Trace Java Methods(跟蹤 Java 方法:在運行時檢測應用剃毒,以在每個方法調用開始和結束時記錄一個時間戳病袄。系統(tǒng)會收集并比較這些時間戳,以生成方法跟蹤數(shù)據(jù)赘阀,包括時間信息和 CPU 使用率益缠。)


圖片1.png
  1. 依次選擇 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)化問題分析的文章就介紹到這了,如果對大家有幫助尺锚,請點贊收藏珠闰,謝謝支持!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末瘫辩,一起剝皮案震驚了整個濱河市伏嗜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伐厌,老刑警劉巖承绸,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挣轨,居然都是意外死亡军熏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門卷扮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荡澎,“玉大人均践,你說我怎么就攤上這事∧︶#” “怎么了彤委?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長或衡。 經(jīng)常有香客問我焦影,道長,這世上最難降的妖魔是什么薇宠? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任偷办,我火速辦了婚禮,結果婚禮上澄港,老公的妹妹穿的比我還像新娘。我一直安慰自己柄沮,他們只是感情好回梧,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祖搓,像睡著了一般狱意。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拯欧,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天详囤,我揣著相機與錄音,去河邊找鬼镐作。 笑死藏姐,一個胖子當著我的面吹牛,可吹牛的內容都是我干的该贾。 我是一名探鬼主播羔杨,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼杨蛋!你這毒婦竟也來了兜材?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤逞力,失蹤者是張志新(化名)和其女友劉穎曙寡,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寇荧,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡举庶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了砚亭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灯变。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡殴玛,死狀恐怖,靈堂內的尸體忽然破棺而出添祸,到底是詐尸還是另有隱情滚粟,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布刃泌,位于F島的核電站凡壤,受9級特大地震影響,放射性物質發(fā)生泄漏耙替。R本人自食惡果不足惜亚侠,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俗扇。 院中可真熱鬧硝烂,春花似錦、人聲如沸铜幽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽除抛。三九已至狮杨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間到忽,已是汗流浹背橄教。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留喘漏,地道東北人护蝶。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像陷遮,于是被迫代替她去往敵國和親滓走。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容