Android 分析實現(xiàn)性能優(yōu)化之啟動速度優(yōu)化
本文主要探討以下幾個問題:
- 啟動方式
- 啟動流程中可優(yōu)化的環(huán)節(jié)
- 檢測工具
- 優(yōu)化點
- 黑白屏問題
啟動方式
應用有三種啟動狀態(tài),每種狀態(tài)都會影響應用向用戶顯示所需的時間:冷啟動、溫啟動與熱啟動
冷啟動(啟動優(yōu)化目標)
冷啟動是指應用從頭開始啟動:系統(tǒng)進程在冷啟動后才創(chuàng)建應用進程。發(fā)生冷啟動的情況包括應用自設(shè)備啟動后或系統(tǒng)終止應用后首次啟動。
熱啟動
在熱啟動中,系統(tǒng)的所有工作就是將 Activity 帶到前臺。只要應用的所有 Activity 仍駐留在內(nèi)存中,應用就不必重復執(zhí)行對象初始化、布局加載和繪制。
溫啟動
溫啟動包含了在冷啟動期間發(fā)生的部分操作;同時,它的開銷要比熱啟動高。有許多潛在狀態(tài)可視為溫啟動。例如:
- 用戶在退出應用后又重新啟動應用。進程可能未被銷毀,繼續(xù)運行,但應用需要執(zhí)行 onCreate() 從頭開始重新創(chuàng)建 Activity。
- 系統(tǒng)將應用從內(nèi)存中釋放,然后用戶又重新啟動它。進程和 Activity 需要重啟,但傳遞到 onCreate() 的已保存的實例savedInstanceState對于完成此任務有一定助益。
- …
啟動流程中可優(yōu)化的環(huán)節(jié)
啟動流程中開發(fā)者可優(yōu)化的環(huán)節(jié)不多,咱們可以從APP啟動流程中尋找下
APP啟動過程如下:
- 點擊桌面App圖標,Launcher進程采用Binder IPC向system_server進程發(fā)起startActivity請求;
- system_server進程接收到請求后,向zygote進程發(fā)送創(chuàng)建進程的請求;
- Zygote進程fork出新的子進程,即App進程;
- 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,并回調(diào)Activity.onCreate()等方法。
- 到此,App便正式啟動,開始進入Activity生命周期,執(zhí)行完onCreate/onStart/onResume方法,UI渲染結(jié)束后便可以看到App的主界面。
所以,我們能優(yōu)化的階段只有 Application.onCreate() —> Activity.onWindowFocusChanged()
檢測工具
啟動時間檢測
啟動的時間怎樣算是合適的?怎樣一個時間范圍內(nèi)用戶是感覺流暢的?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的啟動時間。那我們?nèi)绾闻袛嗍悄男┓椒ê臅r太多導致APP啟動時間過長呢?
CPU profile
API level >= 26
要在應用啟動過程記錄CPU活動,需要做以下操作
1.依次選擇 Run > Edit Configurations
2.勾選 Trace Java Methods(跟蹤 Java 方法:在運行時檢測應用,以在每個方法調(diào)用開始和結(jié)束時記錄一個時間戳。系統(tǒng)會收集并比較這些時間戳,以生成方法跟蹤數(shù)據(jù),包括時間信息和 CPU 使用率。)
3. 依次選擇 Run > Profile,將您的應用部署到搭載 Android 8.0(API 級別 26)或更高版本的設(shè)備上
主要分析的地方有3個: Flame Chart、 Top Down 、bottom up。
API level < 26
對于API低于26的,我們可以調(diào)用 Debug API,調(diào)用起點 Application構(gòu)造函數(shù)
public class MyApplication extends Application { public MyApplication() { // 沒有指定絕對路徑,就是相對路徑,相對 sdcard Debug.startMethodTracing("miss"); } }
調(diào)用終點 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() //未關(guān)閉的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中設(shè)置背景圖的方式來解決。
<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設(shè)置回原來的主題
@Override protected void onCreate(Bundle savedInstanceState) { setTheme(R.style.AppTheme); super.onCreate(savedInstanceState); }
這么做,只是提高啟動的用戶體驗。并不能做到真正的加快啟動速度。
總結(jié):啟動速度優(yōu)化也會涉及到布局優(yōu)化與卡頓優(yōu)化,包括內(nèi)存抖動等問題。優(yōu)化是一條持續(xù)的道路,很多時候我們會發(fā)現(xiàn)通過各種檢測手段花費了大量的精力去對代碼進行修改得到的優(yōu)化效果可能并不理想。因為優(yōu)化就是一點一滴積累下來的,我們平時在編碼的過程中就需要多注意自己的代碼性能。
到此這篇關(guān)于Android 分析實現(xiàn)性能優(yōu)化之啟動速度優(yōu)化的文章就介紹到這了,更多相關(guān)Android 性能優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用SpannableString和ImageSpan在textview中插入圖片的方法
這篇文章主要為大家詳細介紹了利用SpannableString和ImageSpan在textview中插入圖片的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11Android使用ViewBinding的詳細步驟(Kotlin簡易版)
最近這段時間在學習Kotlin,突然發(fā)現(xiàn)谷歌已經(jīng)把kotlin-android-extensions插件廢棄,目前推薦使用ViewBinding來進行替代,接下來通過本文給大家分享Android使用ViewBinding的詳細步驟,感興趣的朋友一起學習吧2021-05-05Android 開發(fā)系統(tǒng)自帶語音模塊應用
本篇文章 主要介紹 Android 開發(fā)自帶語音模塊實例,在開發(fā)Android系統(tǒng)中會用到系統(tǒng)語音搜索模塊,這里給大家一個參考實例2016-07-07Android zxing如何識別反轉(zhuǎn)二維碼詳解
這篇文章主要給大家介紹了關(guān)于Android zxing如何識別反轉(zhuǎn)二維碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-09-09Android程序開發(fā)中單選按鈕(RadioGroup)的使用詳解
在android程序開發(fā)中,無論是單選按鈕還是多選按鈕都非常的常見,接下來通過本文給大家介紹Android程序開發(fā)中單選按鈕(RadioGroup)的使用,需要的朋友參考下吧2016-03-03Android百度地圖定位后獲取周邊位置的實現(xiàn)代碼
這篇文章主要為大家詳細介紹了Android百度地圖定位后獲取周邊位置的實現(xiàn)代碼,準確獲取周邊地理位置,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-01-01Android畫圖實現(xiàn)MPAndroidchart折線圖示例詳解
這篇文章主要為大家介紹了Android畫圖實現(xiàn)MPAndroidchart折線圖示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07