Android啟動優(yōu)化最佳方案:去啟動頁和異步初始化

項目地址:https://github.com/smartzheng/asyncstarter

隨著APP的日漸增大呜舒,集成的三方庫也越來越多青责,導致APP的啟動極其緩慢扣囊。最近在慕課get了一些不錯的優(yōu)化方案饼灿,將原來的冷啟動時間大概提升30%夷家。
啟動的時間監(jiān)測可以直接用adb命令實現(xiàn):

adb shell am start -W PackageName/ActivityName

下面是我未優(yōu)化之前的項目debug版本啟動時間(華為p10plus)腕唧,這里介紹一下幾個概念
ThisTime:最后一個Activity啟動耗時
TotalTime:所有Activity啟動耗時
WaitTimeTime:AMS啟動Activity啟動耗時
可以看到耗時接近1.3s多(1.3s不算長,但是往往應用加固之后還會慢大一截)瘾英。

-> ~ adb shell am start -W com.smartzheng/com.smartzheng.activity.SplashActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.
LAUNCHER]cmp=com.smartzheng/.activity.MainActivity }
Warning: Activity not started, its current task has been brought to the front
Status: ok
Activity: com.uoko.mlgb/.mvp.view.activity.MainActivity
ThisTime: 600
TotalTime: 1301
WaitTime: 1330
Complete

優(yōu)化一:去掉啟動頁
IPC是個比較耗時的操作,往往我們會設置一個閃屏頁颂暇,去掉之后可以一定幅度減少啟動時間缺谴。
我的做法是直接刪除SplashActivity,將MainActivity設為啟動頁。然后在manifests中將其theme設為啟動時的theme:

<activity
    android:name=".activity.MainActivity"
    android:configChanges="screenSize|keyboardHidden|orientation"
    android:launchMode="singleTask"
    android:screenOrientation="portrait"
    android:theme="@style/SplashTheme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
    </intent-filter>
    <intent-filter>
        <data android:scheme="growing.a4ce2f9edf74350a"/>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
    </intent-filter>
</activity>

SplashTheme中windowBackground為啟動圖片(提一句:這里的windowBackground最好是9patch圖片湿蛔,防止拉伸變形)膀曾,這樣設置還有一個好處是可以解決掉APP啟動白屏的問題。

<style name="SplashTheme" parent="AppThemeFullScreen">
    <item name="android:windowBackground">@drawable/splash</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

最后阳啥,在MainActivity的onCreate方法中添谊,手動setTheme更改為Application的默認Theme:

override fun onCreate(savedInstanceState: Bundle?) {
    setTheme(R.style.AppTheme)
    super.onCreate(savedInstanceState)
}

評論中有人問到如果去掉閃屏頁,那廣告位怎么解決察迟?其實廣告頁面的顯示其實用一個單獨的Activity實現(xiàn)不是一個好選擇斩狱,直接調(diào)用Activity的addContentView方法就可以添加一個view在activity上面,在倒計時完成之后再removeContentView扎瓶,這樣隨時都可以在任意activity上添加廣告所踊,通用性和性能都更好。

優(yōu)化二:異步初始化
優(yōu)化之前概荷,我的Application的onCreate是這樣的:

override fun onCreate() {
    super.onCreate()
    installSysExceptionHandler()
    initImPush()
    initGrowing()
    initBaidu()
    initApollo()
    initBugly()
    initIMSdk()
    initPush()
    initRxJava()
    initNineGridView()
    initSeoReport()
    initStrictMode()
    initFonts()
}

每一項初始化任務都是同步執(zhí)行的秕岛。優(yōu)化的思想就是將各個初始化任務放到一個線程池中去執(zhí)行。優(yōu)化之后代碼如下:

override fun onCreate() {
    super.onCreate()
    TaskDispatcher.init(this)
    TaskDispatcher.createInstance().run {
        addTask(InitApolloTask())
            .addTask(InitBaiduTask())
            .addTask(InitBuglyTask())
            .addTask(InitFontTask())
            .addTask(InitGrowingTask())
            .addTask(InitIMPushTask())
            .addTask(InitIMSDKTask())
            .addTask(InitJPushTask())
            .addTask(InitViewTask())
            .addTask(InitRxjavaTask())
       start()
       await()
    }
}

看看優(yōu)化之后的啟動耗時(release環(huán)境下)误证,啟動速度大概提升了近30%:

-> ~ adb shell am start -W com.smartzheng/com.smartzheng.activity.SplashActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.
LAUNCHER]cmp=com.smartzheng/.activity.MainActivity }
Status: ok
Activity: com.uoko.mlgb/.mvp.view.activity.MainActivity
ThisTime: 911
TotalTime: 911
WaitTime: 931
Complete

將各個初始化任務放到線程池執(zhí)行需要解決很多問題:
部分初始化工作只能在主線程執(zhí)行
部分初始化任務需要先執(zhí)行
部分初始化任務需要依賴其他任務執(zhí)行完之后才可以執(zhí)行
部分任務必須執(zhí)行完才能進入Activity頁面
參考課程继薛,將封裝的代碼放到了GitHub,可以直接依賴使用愈捅;具體的實現(xiàn)細節(jié)在源碼中有詳細注釋遏考。使用方法如下:
1.添加倉庫

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  1. 添加依賴
dependencies {
    implementation 'com.github.smartzheng:asyncstarter:1.0.1'
}

3.自定義Task

class InitTask : Task() {
    override fun needWait(): Boolean {//是否需要在阻塞在await(),在Application的onCreate方法之前執(zhí)行完
    return true
    }

    override fun dependsOn(): MutableList<Class<out Task>> {//等待另一個Task執(zhí)行完再執(zhí)行此任務初始化
        return mutableListOf(InitTask1::class.java)
    }
    override fun runOnMainThread(): Boolean {//是否需要運行在主線程
        return true
    }
    override fun needRunAsSoon(): Boolean {//提高優(yōu)先級,也可以指定優(yōu)先級大小priority
        return true
    }
    override fun run() {
        //初始化
    }
}

4.在Application中

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        AsyncStarter.init(this)
        val starter = AsyncStarter.createInstance()

        starter.addTask(InitTask1())
            .addTask(InitTask2())
            .addTask(InitTask3())
            //addTask()...
        starter.start()
        starter.await()
        //Kotlin run
        //AsyncStarter.createInstance()
        //            .run {
        //                addTask(InitTask1())
        //                    .addTask(InitTask2())
        //                    .addTask(InitTask3())
        //                    //addTask()...
        //                    .start()
        //                await()
        //            }
    }
}

詳細的配置解釋和實例可以查看GitHub源碼,其中有詳細注釋改鲫,歡迎star:https://github.com/smartzheng/asyncstarter

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诈皿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子像棘,更是在濱河造成了極大的恐慌稽亏,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缕题,死亡現(xiàn)場離奇詭異截歉,居然都是意外死亡,警方通過查閱死者的電腦和手機烟零,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門瘪松,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锨阿,你說我怎么就攤上這事宵睦。” “怎么了墅诡?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵壳嚎,是天一觀的道長。 經(jīng)常有香客問我,道長烟馅,這世上最難降的妖魔是什么说庭? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮郑趁,結(jié)果婚禮上刊驴,老公的妹妹穿的比我還像新娘。我一直安慰自己寡润,他們只是感情好捆憎,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悦穿,像睡著了一般攻礼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上栗柒,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天礁扮,我揣著相機與錄音,去河邊找鬼瞬沦。 笑死太伊,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的逛钻。 我是一名探鬼主播僚焦,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼曙痘!你這毒婦竟也來了芳悲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤边坤,失蹤者是張志新(化名)和其女友劉穎名扛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茧痒,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡肮韧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了旺订。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弄企。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖区拳,靈堂內(nèi)的尸體忽然破棺而出拘领,到底是詐尸還是另有隱情,我是刑警寧澤樱调,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布院究,位于F島的核電站洽瞬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏业汰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一菩颖、第九天 我趴在偏房一處隱蔽的房頂上張望样漆。 院中可真熱鬧,春花似錦晦闰、人聲如沸放祟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跪妥。三九已至,卻和暖如春声滥,著一層夾襖步出監(jiān)牢的瞬間眉撵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工落塑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纽疟,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓憾赁,卻偏偏與公主長得像污朽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子龙考,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

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