1. 程式人生 > >Android中APP應用冷啟動黑白屏原因 優化解決方案

Android中APP應用冷啟動黑白屏原因 優化解決方案

冷啟動

前言

做過APP開發,尤其是複雜專案的同學應該會經歷過APP在桌面點選冷啟動的時候,你以為會順利開啟應用首頁,但是出現在你眼前的不是白屏就是黑屏的情況,也不會停留多久,可能就一閃而過;不管哪種情況,對於使用者體驗來說肯定是不行的,對於一個優秀程式設計師來說,怎麼能看到自己開發的軟體出現這種情況呢?那這到底怎麼回事呢?今天就來說道說道

應用啟動

應用啟動一般分為冷啟動,熱啟動

  • 冷啟動:這其實是一個從無到有的過程,就是在啟動應用前,系統中沒有該應用的任何程序資訊;比如啟動裝置後第一次啟動這個應用,或者殺死該應用後再啟動這個應用,這些情況都屬於冷啟動;這種啟動方式所消耗的啟動時間是最長的,所做的工作也是最多的
  • 熱啟動:這種就是啟動應用前,系統中已經存在該應用的程序,比如你按back,home鍵回到桌面,再進入應用,這種情況就是熱啟動

我們今天要說的就是冷啟動中出現的一些問題

冷啟動流程

應該說冷啟動是無法避免的,因為一個應用要想展示出來,它總是需要分配一定的記憶體等資訊,而這些東西從無到有總是需要一定的時間,開發者能做的就是將這段等待時間儘可能優雅的給使用者縮短或者隱藏起來

那冷啟動過程到底發生了什麼導致了這些併發症呢,說到這裡就要闡述應用的啟動流程了:

關於應用啟動及程序建立可以參考這幾篇文章
Android之Activity啟動流程原始碼深入解析
解析Android中Zygote程序是如何fork一個APP程序


從Activity載入原始碼深入理解ActivityThrad的工作邏輯

當用戶在Launcher內點選應用圖示,Launcher將這個動作傳送給AMS,AMS判斷這個應用所在程序不存在,那就需要建立一個新的程序;然後AMS傳送訊息給Zygote程序,讓它建立程序;Zygote程序經過一陣fork之後,分配好應用需要的記憶體,就通過反射載入ActivityThread類的main方法,接下來進入應用程序了;ActivityThread的main方法會建立應用的Application,載入主題,建立應用第一個Activity,載入佈局,進行繪製顯示,這樣你就看到第一個Activity了,啟動流程結束

問題原因

但是程序建立,類載入及Activity啟動需要時間,如果啥都不做一直等到Activity渲染完顯示,那這個空白期就很尷尬了,使用者點了之後,啥都沒反應,還停留在桌面,出現了假死現象,使用者可能會再次點選,非常影響使用者體驗

於是Android就推出了一個預覽視窗,應用一開啟就顯示這個視窗,給使用者反饋,表明你點選有效;但是這個視窗展示什麼呢?這時候Activity內容和layout都沒載入完,別擔心,因為此時Androidmanifest裡面的資訊已經讀取到了,系統會將你在manifest檔案設定的主題中android:windowBackground 屬性來設定到DecorView中,你設定的是顏色,那就顯示顏色;設定圖片背景,那就顯示圖片;如果沒有設定,那就預設是一個白屏或者黑屏

看到這裡發現好像嚴格來說這不是問題,反而是個優化的結果;但是對於追求完美的程式猿來說,這種有損應用體驗的情況怎麼能存在呢,一定要解決

解決方法

  • 第一種

既然是這個預覽視窗導致的黑白屏情況,那我們就禁用這個預覽視窗,使用如下這個屬性

<item name="android:windowDisablePreview">true</item>

這種做法雖然沒有預覽視窗了,但是會出現在桌面點選應用圖示後,短暫停滯一段時間才打開APP

這個做法個人不推薦,直接把Google做的優化給取消了;但是我發現平時用的一些APP就是這種做法

  • 第二種

將背景設定透明

<item name="android:windowBackground">@android:color/transparent</item>

這種做法也不推薦,會出現點選圖示後,到出現Activity內容是一個閃爍的過程;以及按home鍵回到應用列表也是一個閃爍的過程,影響使用者體驗

  • 第三種

將windowBackground屬性設定成一張APP啟動頁一樣的背景圖,這樣給使用者的感覺是APP秒啟動,因為預覽視窗跟啟動頁幾乎一模一樣;如果啟動頁有其它後續載入的View,就會給人重新整理不同步的感覺,不過市面上大部分應用啟動頁都是一個靜態背景圖,可以採用這種方法

<item name="android:windowBackground">@mipmap/img_app</item>

但是要注意,這裡設定的背景圖是常駐記憶體的,所以在離開預覽視窗後,比如在歡迎頁或者應用首頁需要將背景圖置null

getWindow().setBackgroundDrawable(null);

優化

上面說的幾種方法都是很直接的,其實還有一些優化可以讓預覽視窗存在的時間更短點

  • 在開發應用的時候,基本上都會繼承Application類,寫一寫自己的邏輯;熟悉應用啟動流程的應該知道,應用啟動後,是先回調Application的onCreate方法,然後再去載入Activity;但是我們在開發過程中難免會依賴一些第三方庫或者元件,同時還會初始化一些資源等操作,這機會導致Activity的載入時間更加延後了

    所以這裡就需要進行一些優化:
    比如不要做IO操作或者其它耗時操作,儘量不要執行太多靜態資料操作,儘量不要做單例物件的初始化操作;反正能往後做的事情儘量別放到Application做

  • 對於Activity的佈局,不要巢狀過多,影響繪製效率;過多的控制元件可以使用ViewStub,針對指定的業務場景,初始化指定的控制元件;在歡迎頁儘量少做檔案操作,比如資料庫,SharedPreferences等

其實每個應用都有每個應用的特點,優化也不能以一概全,大家還是得根據自己的APP的特點去做針對性的處理