Android - 啟動(dòng)白屏分析與優(yōu)化

記錄一次項(xiàng)目開發(fā)中的一個(gè)小問題代态,最近發(fā)現(xiàn)公司的項(xiàng)目啟動(dòng)白屏的時(shí)間非常長久,在高端機(jī)也要2-3秒疹吃,那么在低端機(jī)豈不是更久,別人打開你的APP蹦疑,發(fā)現(xiàn)一篇白或者一片黑,很不友好萨驶,不懂的人還以為開發(fā)者很水歉摧。
先上一張我項(xiàng)目的啟動(dòng)時(shí)間


原始時(shí)間圖.png

其實(shí)我的東西也不多,要3秒鐘。所以App啟動(dòng)的時(shí)候會(huì)出現(xiàn)白屏(黑屏),非常不友好腔呜。網(wǎng)上有一種解決方案比較多人知道.就是將主題(白色/黑色)設(shè)置成自己SplashActivity的效果一樣的話叁温。用戶誤以為白屏就是正在啟動(dòng)的啟動(dòng)頁,但是這種做法實(shí)際上并不能減少App啟動(dòng)的時(shí)間,只是將白屏的時(shí)候換上了一個(gè)跟啟動(dòng)頁一樣的背景。下面我講兩種做法核畴。

下面跟大家科普一下啟動(dòng)模式膝但。聽到啟動(dòng)模式,大家會(huì)想到4大啟動(dòng)模式 ?相信Activity的啟動(dòng)模式大家復(fù)習(xí)基礎(chǔ)知識(shí)面試的時(shí)候已經(jīng)背爛了,我今天講的不是Activity的啟動(dòng)模式谤草,而是應(yīng)用的啟動(dòng)模式跟束。

應(yīng)用的啟動(dòng)方式

1、冷啟動(dòng):系統(tǒng)的進(jìn)程沒有丑孩,直到此開始冀宴,創(chuàng)建了應(yīng)用程序的進(jìn)程。 在應(yīng)用程序自設(shè)備啟動(dòng)以來第一次啟動(dòng)或系統(tǒng)殺死應(yīng)用程序等情況下會(huì)發(fā)生冷啟動(dòng)温学。 這種類型的啟動(dòng)在最小化啟動(dòng)時(shí)間方面是最大的挑戰(zhàn)略贮,因?yàn)橄到y(tǒng)和應(yīng)用程序比其他啟動(dòng)狀態(tài)具有更多的工作。

2仗岖、熱啟動(dòng):與冷啟動(dòng)相比逃延,熱啟動(dòng)應(yīng)用程序要簡(jiǎn)單得多,開銷更低箩帚。在熱啟動(dòng)真友,所有的系統(tǒng)都是把你的活動(dòng)到前臺(tái)。如果所有應(yīng)用程序的活動(dòng)仍駐留在內(nèi)存中紧帕,那么應(yīng)用程序可以避免重復(fù)對(duì)象初始化盔然,UI的布局和渲染。
熱啟動(dòng)顯示與冷啟動(dòng)場(chǎng)景相同的屏幕行為:系統(tǒng)進(jìn)程顯示空白屏幕是嗜,直到應(yīng)用程序完成呈現(xiàn)活動(dòng)愈案。

3、溫啟動(dòng):用戶退出您的應(yīng)用鹅搪,但隨后重新啟動(dòng)站绪。該過程可能已繼續(xù)運(yùn)行,但應(yīng)用程序必須通過調(diào)用onCreate()從頭開始重新創(chuàng)建活動(dòng)丽柿。系統(tǒng)從內(nèi)存中驅(qū)逐您的應(yīng)用程序恢准,然后用戶重新啟動(dòng)它魂挂。進(jìn)程和Activity需要重新啟動(dòng),但任務(wù)可以從保存的實(shí)例狀態(tài)包傳遞到onCreate()中馁筐。

為什么出現(xiàn)白屏

Application的構(gòu)造器方法——>attachBaseContext()——>onCreate()——>Activity的構(gòu)造方法——>onCreate()——>配置主題中背景等屬性——>onStart()——>onResume()——>測(cè)量布局繪制顯示在界面上涂召。
從你點(diǎn)擊桌面的圖標(biāo)開始安卓系統(tǒng)會(huì)從Zygote進(jìn)程中fork創(chuàng)建出一個(gè)新的進(jìn)程分配給該應(yīng)用,之后會(huì)依次創(chuàng)建和初始化Application類敏沉。當(dāng)這些操作走完之后,你才能看到SplashActivity的第一眼果正。那么這期間你Application里onCreate做了N多的SDK的初始化,這段時(shí)間您的屏幕都是你手機(jī)默認(rèn)主題的顏色(白色/黑色)盟迟。這就是為什么我們做的APP會(huì)出現(xiàn)白屏秋泳。

優(yōu)化方案

解決方案一 修改啟動(dòng)Activity的主題

步驟一 styles.xml 添加Style

 <style name="SplashTheme" parent="AppTheme">
        <!-- 將splash圖片設(shè)置在這,這樣這張圖片取代白屏 -->
        <item name="android:windowBackground">@drawable/bg_splash</item>
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
 </style>

步驟二 AndroidManifest.xml 添加啟動(dòng)頁主題

<activity
      android:name=".SplashActivity"
      android:theme="@style/SplashTheme">
      <intent-filter>
             <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
 </activity>

解決方案二

既然是Application里做了很多耗時(shí)的初始化導(dǎo)致啟動(dòng)耗時(shí),那么我們可以試著優(yōu)化一下這里的初始化攒菠。介紹一樣?xùn)|西 :IntentService 迫皱。Service大家應(yīng)該會(huì)比較熟悉,那我簡(jiǎn)單的科普一下這個(gè)類。

IntentService

IntentService is a base class for Service that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
This “work queue processor” pattern is commonly used to offload tasks from an application’s main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.
All requests are handled on a single worker thread – they may take as long as necessary (and will not block the application’s main loop), but only one request will be processed at a time.
IntentService是Service的子類要尔,根據(jù)需要處理異步請(qǐng)求(以intent表示)舍杜。客戶端通過調(diào)用startService(Intent) 發(fā)送請(qǐng)求赵辕,該Service根據(jù)需要啟動(dòng)既绩,使用工作線程處理依次每個(gè)Intent,并在停止工作時(shí)停止自身还惠。
這種“工作隊(duì)列處理器”模式通常用于從應(yīng)用程序的主線程中卸載任務(wù)饲握。 IntentService類的存在是為了簡(jiǎn)化這種模式。 要使用它蚕键,擴(kuò)展IntentService并實(shí)現(xiàn)onHandleIntent(Intent)救欧。 IntentService將收到Intents,啟動(dòng)一個(gè)工作線程锣光,并根據(jù)需要停止該服務(wù)笆怠。
所有請(qǐng)求都在單個(gè)工作線程處理 - 它們可能需要很長的時(shí)間(并且不會(huì)阻止應(yīng)用程序的主循環(huán)),但是一次只會(huì)處理一個(gè)請(qǐng)求誊爹。

IntentService與Service的區(qū)別

Android中的Service是用于后臺(tái)服務(wù)的蹬刷,當(dāng)應(yīng)用程序被掛到后臺(tái)的時(shí)候,問了保證應(yīng)用某些組件仍然可以工作而引入了Service這個(gè)概念频丘,那么這里面要強(qiáng)調(diào)的是Service不是獨(dú)立的進(jìn)程办成,也不是獨(dú)立的線程,它是依賴于應(yīng)用程序的主線程的搂漠,也就是說迂卢,在更多時(shí)候不建議在Service中編寫耗時(shí)的邏輯和操作,否則會(huì)引起ANR。

那么我們當(dāng)我們編寫的耗時(shí)邏輯而克,不得不被service來管理的時(shí)候靶壮,就需要引入IntentService,IntentService是繼承Service的拍摇,那么它包含了Service的全部特性亮钦,當(dāng)然也包含service的生命周期,那么與service不同的是充活,IntentService在執(zhí)行onCreate操作的時(shí)候,內(nèi)部開了一個(gè)線程蜡娶,去你執(zhí)行你的耗時(shí)操作混卵。

上面純粹幫你們百度了一波,其實(shí)我也不是很懂窖张,直接上代碼吧幕随。

InitIntentService.java

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.Nullable;

/**
 * Created by 賣火柴的小女孩 - Jc on 2018/8/8.
 */

public class InitIntentService extends IntentService {

    private static final String ACTION_INIT = "com.hjc.helloworld.action.INIT";

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     */
    public InitIntentService() {
        super("InitIntentService");
    }

    public static void start(Context context) {
        Intent intent = new Intent(context, InitIntentService.class);
        intent.setAction(ACTION_INIT);
        context.startService(intent);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        if (intent != null && ACTION_INIT.equals(intent.getAction()))
        {
            //執(zhí)行百度地圖初始化
            //Push初始化
            //友盟初始化
            //....N多第三方初始化
        }
    }
}

App.java


import android.app.Application;

/**
 * Created by 賣火柴的小女孩 - Jc on 2018/8/8.
 */

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        InitIntentService.start(this);
    }
}

AndroidManifest.xml

<service  android:name=".InitIntentService"/>

其實(shí)你可以理解開辟了另一個(gè)空間去執(zhí)行各種第三方啟動(dòng)的耗時(shí)操作∷藿樱看完本文的小伙伴,結(jié)合解決方案一和解決方案二,理論上能很大的解決APP啟動(dòng)白屏的問題了赘淮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市睦霎,隨后出現(xiàn)的幾起案子梢卸,更是在濱河造成了極大的恐慌,老刑警劉巖副女,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛤高,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡碑幅,警方通過查閱死者的電腦和手機(jī)戴陡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沟涨,“玉大人恤批,你說我怎么就攤上這事」埃” “怎么了喜庞?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長篮昧。 經(jīng)常有香客問我赋荆,道長,這世上最難降的妖魔是什么懊昨? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任窄潭,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嫉你。我一直安慰自己月帝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布幽污。 她就那樣靜靜地躺著嚷辅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪距误。 梳的紋絲不亂的頭發(fā)上簸搞,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音准潭,去河邊找鬼趁俊。 笑死,一個(gè)胖子當(dāng)著我的面吹牛刑然,可吹牛的內(nèi)容都是我干的寺擂。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼泼掠,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼怔软!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起择镇,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤挡逼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后沐鼠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挚瘟,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年饲梭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乘盖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡憔涉,死狀恐怖订框,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兜叨,我是刑警寧澤穿扳,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站国旷,受9級(jí)特大地震影響矛物,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜跪但,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一履羞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦忆首、人聲如沸爱榔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽详幽。三九已至,卻和暖如春浸锨,著一層夾襖步出監(jiān)牢的瞬間唇聘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國打工柱搜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雳灾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓冯凹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親炒嘲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宇姚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請(qǐng)注明出處:http://eddy.wiki/interview-androi...
    eddy_wiki閱讀 3,256評(píng)論 0 20
  • 2.1 Activity 2.1.1 Activity的生命周期全面分析 典型情況下的生命周期:在用戶參與的情況下...
    AndroidMaster閱讀 3,031評(píng)論 0 8
  • 【Android Service】 Service 簡(jiǎn)介(★★★) 很多情況下夫凸,一些與用戶很少需要產(chǎn)生交互的應(yīng)用程...
    Rtia閱讀 3,143評(píng)論 1 21
  • 1.什么是Activity?問的不太多夭拌,說點(diǎn)有深度的 四大組件之一,一般的,一個(gè)用戶交互界面對(duì)應(yīng)一個(gè)activit...
    JoonyLee閱讀 5,729評(píng)論 2 51
  • 這件事發(fā)生距離現(xiàn)在大概有30多天了吧魔熏,我實(shí)在撐不住,打算把它寫出來鸽扁,也許你們不會(huì)相信蒜绽,甚至是我自己都覺得是在做夢(mèng),...
    咚咚咚咚咚咚閱讀 588評(píng)論 2 12