性能優化的目的不是爲了優化而優化,並且爲了之後再也不優化, 給本身統一 一個標準。php
這裏也許會有人問 APP 啓動還須要優化嗎?啓動又不是咱們本身寫的代碼,難道 Google 工程師會犯這麼低級的錯嗎?其實這還真不是 Google 的錯,應該說是給咱們開發者留了一個坑吧。應該有的同窗知道是怎麼一回事兒了,當咱們在系統桌面任意點擊一個 APP 是否是會發現啓動的時候有一瞬間有白屏出現(之前老版本是黑屏) 那麼咱們怎麼來優化這個黑白屏的問題勒,如今咱們先來了解一下 Android 手機重開機到啓動 APP 的過程吧css
這裏會設計到 Android 系統源碼的知識,但並不會深刻解析源碼,咱們只是瞭解一個過程,由於太深刻我本身也懵。java
我在這裏大體分爲了 6 個步驟,下面以流程圖爲準android
首先拿到一部 Android 系統的手機打開電源,引導芯片代碼加載引導程序 BootLoader 到 RAM 中去執行。shell
BootLoader 把操做系統拉起來。數據庫
Linux 內核啓動開始系統設置,找到一個 init.rc 文件啓動初始化進程。性能優化
init 進程初始化和啓動屬性服務,以後開啓 Zygote 進程。網絡
Zygote 開始建立 JVM 並註冊 JNI 方法,開啓 SystemServer。架構
啓動 Binder 線程池和 SystemServiceManager,並啓動各類服務。app
手機回到系統桌面, 經過 adb shell dumpsys window w |findstr / |findstr name= 來查看當前的進程和 Activity 名。
當點擊桌面 APP 圖標的時候會走 Launcher . java 的 onClick (View view) 方法,詳細見下圖。
AcitivityThread main() 調用執行流程,見下圖。
最後 ActivityThread main() 是經過反射來進行初始化的
ActivityThread.java 作爲入口,詳細解說 main() 函數,仍是以一個動畫來演示一下吧;
根據上面的動畫,你們應該已經明白 ActivityThread.java main() 方法中 Appcation onCreate() 的是怎麼被調用起來的吧
不知道你們有沒有注意 ActivityThread main() 中 Looper.prepareMainLooper(); 其實我們爲何可以在 Main Thread 中建立 Handler 不會報錯了吧,是由於 Activity 啓動的時候在這裏已經默認開啓了 Looper。
終於到了正題了,下面咱們就來講下啓動黑白屏的問題,仍是先來看一個 GIF 吧。
從上面的一段錄屏咱們能夠發現市面上常見的 APP 啓動有的是白屏有的是作了優化。黑屏只有在 Android 4.n 具體是哪一個版本我也忘了。那麼如今咱們就以我如今的真實項目來優化一下啓動。
首先爲何會形成白屏勒咱們來看一段源碼
最後就是這個 windowBackground 搞的鬼,知道了是這個搞的鬼那麼咱們就能夠來進行優化了。
在本身的 AppTheme 中加入 windowBackground
設置 windowbackgroud 爲透明的
<item name="android:windowIsTranslucent">true</item>
可是:
這 2 中方法會有一個問題,就是全部的 Activity 啓動都會顯示。
單獨作成一個 AppTheme.Launcher
<style name="AppTheme.Launcher"> <item name="android:windowFullscreen">true</item> <!--<item name="android:windowDisablePreview">true</item>--> <item name="android:windowBackground">@color/colorAccent</item> </style>
在清單文件中 啓動 Activity 加入該 主題
<activity android:name="com.t01.android.dida_login.mvp.ui.activity.LoginActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/AppTheme.Launcher" android:windowSoftInputMode="adjustUnspecified|stateHidden"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
在啓動 Activity 頁面中加入
setTheme(R.style.AppTheme_Launcher);
最後這樣作只有啓動的 UI 才能見到本身的樣式
最後效果,由於我這裏沒有背景圖,故弄了一個主題顏色,若是想要設置一張背景圖片能夠參考下面的示例,否則有可能會引發圖片拉伸效果。
我這裏啓動時間大概在 500 ms ~ 800 ms 左右。
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <bitmap android:src="@mipmap/app_bg" android:gravity="fill"/> </item> </layer-list> 最後在清單 啓動 Activity 的 Theme 中修改成 <item name="android:windowBackground">@drawable/app_theme_bg</item>
聽說 QQ 的實現方法是(這裏只作參考,感興趣的同窗能夠本身試試。)
<item name="android:windowDisablePreview">true</item> <item name="android:windowBackground">@null</item>
adb shell am start -W packName/activity 全路徑
經過關鍵字 Displayed 並篩選爲 No Filters
2019-04-25 18:35:57.629 508-629/? I/ActivityManager: Displayed com.lingyi.autiovideo.lykj/com.t01.android.dida_login.mvp.ui.activity.LoginActivity: +844ms
//開始計時 Debug.startMethodTracing(filePath); 中間爲須要統計執行時間的代碼 //中止計時 Debug.stopMethodTracing();
仍是經過一組動畫來看我怎麼操做的吧。(注意這裏的時間是 微妙 微妙/10^6 = s 應該是這樣,忘了)
`這個工具能夠很友好的提示每一個函數具體在內部執行了多少時間,卡頓其實也能夠用這個方法來進行監測
導出 trace 文件命令
adb pull /storage/emulated/0/appcation_launcher_time.trace
我這裏耗時還不算太大 大概在 0.2 - 0.3 s 左右。
最後啓動優化能夠配合上面的 3 點優化方案 + Appcation 優化方案 = 你本身最優方案。
若是你以爲文章寫得不錯就給個讚唄?若是你以爲那裏值得改進的,請給我留言。必定會認真查詢,修正不足。謝謝。
但願讀到這的您能轉發分享和關注一下我,之後還會更新技術乾貨,謝謝您的支持!
這裏,筆者分享一份從架構哲學的層面來剖析的視頻及資料分享給你們梳理了多年的架構經驗,籌備近1個月最新錄製的,相信這份視頻能給你帶來不同的啓發、收穫
領取方式:獲取免費架構視頻資料請查看我主頁
轉發+點贊+關注,第一時間獲取最新知識點
Android架構師之路很漫長,一塊兒共勉吧!