啓動優化

 

前言

以前有讀者說到關於Android性能優化,性能優化包括不少方面,好比:php

啓動優化、佈局優化、內存優化、卡頓優化、網絡優化、數據庫優化、內存泄漏優化、包體積優化等等。java

後面咱們會依次聊聊,今天就從啓動優化聊起android

冷啓動、溫啓動、熱啓動

首先了解下啓動的這三個概念,也是面試常被問到的:web

  • 冷啓動。冷啓動指的是該應用程序在此以前沒有被建立,發生在應用程序首次啓動或者自上次被終止後的再次啓動。簡單的說就是app進程尚未,須要建立app的進程並啓動app。

好比開機後,點擊屏幕的app圖標啓動應用。面試

冷啓動的過程主要分爲兩步:數據庫

1)系統任務。加載並啓動應用程序;顯示應用程序的空白啓動窗口;建立APP進程 數組

2)APP進程任務。啓動主線程;建立Activity;加載佈局;屏幕布局;繪製屏幕緩存

其實這不就是APP的啓動流程嘛?因此冷啓動是會完整走完一個啓動流程的,從系統到進程。性能優化

  • 溫啓動。溫啓動指的是App進程存在,但Activity可能由於內存不足被回收,這時候啓動App不須要從新建立進程,只須要執行APP進程中的一些任務,好比建立Activity。

好比返回Home後,又繼續使用其餘的APP,時間久了或者打開的應用多了,以前應用的Activity有可能被回收了,可是進程還在。網絡

因此溫啓動過程至關於執行了冷啓動的第二過程,也就是APP進程任務,須要從新啓動線程,Activity等。

  • 熱啓動。熱啓動就是指App進程存在,而且Activity對象仍然存在內存中沒有被回收。

好比app被切到後臺,再次啓動app的過程。

因此熱啓動的開銷最少,這個過程只會把Activity從後臺展現到前臺,無需初始化,佈局繪製等工做。

優化點

三種啓動方式中,冷啓動經歷的時間最長,也是走完了最完整的啓動流程,因此咱們再次分析下冷啓動的啓動流程,看看有哪些能夠優化的點:

  • Launcher startActivity
  • AMS startActivity
  • Zygote fork 進程
  • ActivityThread main()
  • ActivityThread attach
  • handleBindApplication
  • attachBaseContext
  • Application attach
  • installContentProviders
  • Application onCreate
  • Looper.loop
  • Activity onCreate,onResume

縱觀整個流程,其實咱們能動的地方很少,無非就是Application的attach,onCreate方法,Activity的onCreate,onResume方法,這些方法也就是咱們的優化點。

優化方案

1)消除啓動時的白屏/黑屏

App啓動的時候會有一個白屏/黑屏時間,咱們能夠經過設置windowBackground屬性來給啓動的Activity提供一個drawable,這樣就給用戶一個快遞啓動的假象了。

<activity ...
android:theme="@style/MyAppTheme" />

<style name="MyAppTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@drawable/logo</item> 
</style>

2)第三方庫懶加載/異步加載

ApplicationonCreate方法中,總會有不少初始化操做,好比友盟,數據庫,網絡請求庫,廣告SDK等等。

對此,咱們能作的有哪些呢?

  • 異步加載。有些庫不須要在主線程進行初始化,那麼咱們就能夠在子線程中進行初始化,進行異步加載。
  • 延遲加載。有些庫沒必要要一開始就初始化,咱們能夠按需初始化,將一些庫放到用它的時候再初始化,或者放到啓動頁去進行初始化。

因此須要咱們對這些初始化操做進行分析,哪些須要在主線程進行,哪些能夠延遲加載,哪些初始化任務有前後關係等等。這裏涉及到一個啓動器的概念,啓動器的用處就是能夠充分利用CPU多核,自動梳理任務順序。有空的朋友能夠去了解下。

這裏還須要注意一點就是線程的使用:

  • 即不要頻繁建立線程,線程的頻繁建立是耗性能的,因此須要用到 線程池去執行異步任務。

3)預建立Activity

Java中的對象第一次建立的時候,java虛擬機首先檢查類對應的Class對象是否已經加載。若是沒有加載,jvm會根據類名查找.class文件,將其Class對象載入。同一個類第二次new的時候就不須要加載類對象,而是直接實例化,建立時間就縮短了。

今日頭條中就有這種作法,先建立一個Activity的實例。

4)預加載數據

在咱們的啓動頁或者主頁能夠將一些要用到的數據保存到內存或者數據庫,那麼其餘頁面要用到這些數據的時候就能夠直接使用並顯示了。

5)Multidex預加載優化

因爲65536方法限制,因此通常class文件要生成多個dex文件,Android5.0如下,ClassLoader加載類的時候只會從class.dex(主dex)里加載,因此要執行MultiDex.install(context)方法才能正常讀取全部的dex類。

而這個install方法就是耗時大戶,會解壓apk,遍歷dex文件,壓縮dex、將dex文件經過反射轉換成DexFile對象、反射替換數組。

這裏須要的方案就是今日頭條方案:

  • 在Application的attachBaseContext方法裏,啓動另外一個進程的LoadDexActivity去異步執行MultiDex邏輯,顯示Loading。

  • 而後主進程Application進入while循環,不斷檢測MultiDex操做是否完成 ,MultiDex執行完以後主進程Application繼續執行ContentProvider初始化和Application onCreate方法,也就是主進程正常的邏輯。

因此重點就是單開進程去執行MultiDex邏輯,這樣就不影響APP的啓動了。

固然,這僅僅針對5.0如下加載Multidex狀況,5.0以上默認使用ART加載類,安裝時候就已經轉換dex文件爲oat文件了,因此無需優化Multidex狀況了。

6)Webview啓動優化

若是咱們的主頁涉及到Webview,那咱們還要處理WebView的優化。由於Webview的建立很耗時,因此咱們採起如下方案進行Webview的優化:

  • 預先建立WebView,提早將其內核初始化。
  • 使用WebView緩存池,從緩存池中拿到Webview實例。
  • 本地提供靜態頁面資源。

7)避免佈局嵌套

若是啓動頁和主頁的佈局比較複雜,也會影響咱們的啓動時間,因此注意咱們的佈局,多用merge,include,constraintlayout等,特別是多層嵌套問題。

總結

最後再和你們回顧下今天說到的啓動優化方案:

  • 消除啓動時的白屏/黑屏。windowBackground。
  • 第三方庫懶加載/異步加載。線程池,啓動器。
  • 預建立Activity。對象預建立。
  • 預加載數據。
  • Multidex預加載優化。5.0如下多dex狀況。
  • Webview啓動優化。預建立,緩存池,靜態資源。
  • 避免佈局嵌套。多層嵌套。

爲了方便記憶,我再整理成如下三類,分別是Application、Activity、UI

  • Application 三方庫,Multidex。
  • Activity 預建立類,預加載數據。
  • UI方面 windowBackground,佈局嵌套,webview。

參考

 

 

感謝你們的閱讀,有一塊兒學習的小夥伴能夠關注下公衆號—碼上積木❤️

每日三問知識點/面試題,聚沙成塔。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索