App啟動優(yōu)化(三)啟動優(yōu)化方案

如需轉(zhuǎn)載請評論或簡信,并注明出處适秩,未經(jīng)允許不得轉(zhuǎn)載

系列文章

目錄

前言

前面的章節(jié)我們已經(jīng)介紹了啟動分類的啟動流程,同時也介紹了啟動時間的測量方式寇窑。接下來將介紹兩種啟動優(yōu)化方式 — 視覺優(yōu)化和異步優(yōu)化

視覺優(yōu)化

app啟動后鉴象,WindowManager會先加載app theme中的windowBackground梨撞,所以通常就會出現(xiàn)白屏的情況(取決于你的主題是Dark還是Light),我們對windowBackground進行設(shè)置渐北,讓用戶從視覺上感覺app的啟動變快

解決方案

  1. 新增一個主題樣式阿逃,設(shè)置windowBackground屬性,在其中放一張背景圖片,或是廣告圖片之類的
<style name="AppTheme.Launcher" parent="Theme.AppCompat.Light.NoActionBar">
     <item name="android:windowBackground">@drawable/bg_launcher</item
</style>

bg_launcher.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/ic_android" />
    </item>
</layer-list>
  1. MainActivity設(shè)置主題
<activity android:name=".MainActivity"
    android:theme="@style/AppTheme.Launcher">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
  1. MainActivityonCreate()方法執(zhí)行前將主題替換回原來的樣式
@Override
protected void onCreate(Bundle savedInstanceState) {
    //替換為原來的主題,在onCreate之前調(diào)用
    setTheme(R.style.AppTheme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

這種方式雖然不能加快應(yīng)用的啟動時間恃锉,但是可以防止應(yīng)用啟動白屏搀菩,帶來更好的用戶體驗

異步優(yōu)化

如何進行異步優(yōu)化

核心思想:子線程分擔(dān)主線程任務(wù),通過并行減少時間

異步優(yōu)化.png

異步優(yōu)化的思想其實很明確破托,也很容易理解肪跋,但是真正在異步優(yōu)化的實踐過程中,其實是有很多“坑”的

這里寫了一個簡單的demo土砂,我們在Application中進行了一些初始化操作州既,實際場景往往比這要復(fù)雜很多

Application.java

@Override
public void onCreate() {
    super.onCreate();
    //高德地圖
    initAMap();

    //weex
    initWeex();

    //Stecho
    initStetho();

    //圖片加載
    initFresco();

    //自己寫的代碼
    initDeviceId();

    //推送
    initJPush();
}

顯然,上面這種初始化方式是串行的萝映,如果初始化的內(nèi)容過多吴叶,顯然啟動速度就會變慢。結(jié)合我們說的異步初始化的思想锌俱,我們使用了線程池來來優(yōu)化我們的初始化晤郑,使得初始化代碼能夠并行

這里的CORE_POOL_SIZE我們參照了AsyncTask的源碼,根據(jù)cpu數(shù)量來確定線程池的核心池的數(shù)量

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool, 
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));

@Override
public void onCreate() {
    super.onCreate();
    mApplication = this;
    ExecutorService service = Executors.newFixedThreadPool(CORE_POOL_SIZE);
    service.submit(new Runnable() {
        @Override
        public void run() {
            //高德地圖
            initAMap();
        }
    });

    service.submit(new Runnable() {
        @Override
        public void run() {
            //weex
            initWeex();
        }
    });
    
    service.submit(new Runnable() {
            @Override
            public void run() {
                //Stecho
                initStetho();
            }
        });
    
    ....
}

如果對線程池比較熟的人會知道贸宏,現(xiàn)在ApplicationonCreate()方法一定執(zhí)行的特別快造寝。但是有的人可能會問,這里我們能不能把所有初始化方法都放到一個Runnable中去呢吭练?

這樣做理論上其實是可以的诫龙,因為它是異步的,但是上面說了鲫咽,我們這里其實是根據(jù)cpu數(shù)量來確定線程池的核心池的數(shù)量签赃,假設(shè)創(chuàng)建出來3個線程,但是我們只用了一個分尸,那這樣顯然是一種資源的浪費锦聊,所以我們采取了對每個初始化方法都進行了submit的方式

異步優(yōu)化.png

我們可以看到,通過異步的方式進行初始化箩绍,效果是很明顯的

異步優(yōu)化的問題

見識到了異步優(yōu)化的成果孔庭,但是先不要急著高興,簡單思考一下的話我們就會發(fā)現(xiàn)材蛛,這種方式其實是并不完全合理的圆到,很多場景下我們實際上并不能直接使用這種方案,這里舉幾個例子

  1. 不符合異步要求卑吭。實際項目初始化往往比較復(fù)雜芽淡,有時候會遇到某些初始化方法一定要在主線程執(zhí)行,那么用上面這種方式顯然也是不可行的
  2. 需要在某階段完成豆赏。例如我們在閃屏頁面就要用到weex的相關(guān)方法挣菲,這時候如果weex在子線程還沒有初始化成功富稻,顯然就會有問題
  3. 任務(wù)之間有依賴關(guān)系。例如我們這里的initJPush()方法己单,這個方法需要用到DeviceId唉窃,所以就需要在 initDeviceId()之后執(zhí)行

針對問題1,我們需要修改我們的代碼纹笼,把不符合異步要求的方法放到主線程執(zhí)行

針對問題2纹份,這里介紹一個小技巧,我們用到了CountDownLatch廷痘,構(gòu)造方法中傳入1蔓涧,這里的意思是countDownLatch必須被滿足一次,也就是說直到 countDownLatch.countDown()被執(zhí)行笋额,否則countDownLatch.await()會一直等待

    private CountDownLatch countDownLatch = new CountDownLatch(1); 

    @Override
    public void onCreate() {
        super.onCreate();
        mApplication = this;
        ExecutorService service = Executors.newFixedThreadPool(CORE_POOL_SIZE); 
        
        .....
        
        service.submit(new Runnable() {
            @Override
            public void run() {
                //weex
                initWeex();
                countDownLatch.countDown();
            }
        });

        .....

        try {
            countDownLatch.await();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

針對問題3元暴,我們很容易想到下面這種方式,把initDeviceId()放到initJPush()之前

service.submit(new Runnable() {
    @Override
    public void run() {
        initDeviceId();
        initJPush();
    }
});

這樣做的話兄猩,看起來好像解決了問題茉盏。但是實際場景往往很復(fù)雜,有很多類似的這種依賴關(guān)系枢冤,我們很可能遇到一個情況鸠姨,就是我們并不能直接把某個初始化方法移到同一個Runnable

我們上面這種寫法還有一個很大的問題,就是代碼不優(yōu)雅淹真,如果實際項目中有一百個初始化項目呢讶迁?難道就要寫一百次service.submit()方法,我相信很多同學(xué)肯定是無法接受的核蘸,因為不優(yōu)雅的代碼同時也帶了很高的維護成本

總結(jié)

本文介紹了兩個比較常規(guī)的啟動優(yōu)化方案巍糯,一個是視覺優(yōu)化,一個是異步優(yōu)化客扎。但是經(jīng)過本文的分析祟峦,我們看到了,常規(guī)的異步優(yōu)化方法徙鱼,在真實項目中實施起來搀愧,其實是存在很多問題的。那我們?nèi)绾蝸斫鉀Q這些問題呢疆偿?請看啟動優(yōu)化(四),直接項目奉上搓幌,有興趣可以自己看看杆故,具體分析可能要等到哪天有空我想分析的時候了。溉愁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載处铛,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者饲趋。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市撤蟆,隨后出現(xiàn)的幾起案子奕塑,更是在濱河造成了極大的恐慌,老刑警劉巖家肯,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄砰,死亡現(xiàn)場離奇詭異,居然都是意外死亡讨衣,警方通過查閱死者的電腦和手機换棚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來反镇,“玉大人固蚤,你說我怎么就攤上這事〈醪瑁” “怎么了夕玩?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惊豺。 經(jīng)常有香客問我燎孟,道長,這世上最難降的妖魔是什么扮叨? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任缤弦,我火速辦了婚禮,結(jié)果婚禮上彻磁,老公的妹妹穿的比我還像新娘碍沐。我一直安慰自己,他們只是感情好衷蜓,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布累提。 她就那樣靜靜地躺著,像睡著了一般磁浇。 火紅的嫁衣襯著肌膚如雪斋陪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天置吓,我揣著相機與錄音无虚,去河邊找鬼。 笑死衍锚,一個胖子當(dāng)著我的面吹牛友题,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播戴质,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼度宦,長吁一口氣:“原來是場噩夢啊……” “哼踢匣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起戈抄,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤离唬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后划鸽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體输莺,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年漾稀,在試婚紗的時候發(fā)現(xiàn)自己被綠了模闲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡崭捍,死狀恐怖尸折,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情殷蛇,我是刑警寧澤实夹,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站粒梦,受9級特大地震影響亮航,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匀们,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一缴淋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泄朴,春花似錦重抖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至局扶,卻和暖如春恨统,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背三妈。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工畜埋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畴蒲。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓由捎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親饿凛。 傳聞我的和親對象是個殘疾皇子狞玛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

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