是什么拖慢了你的 App 啟動?干掉它!
你的應(yīng)用,啟動夠快嗎?
App 啟動時(shí),我們通常會執(zhí)行很多既定的任務(wù),比如各種 SDK 的初始化、各種數(shù)據(jù)的初始化等。這必將拖慢 App 的啟動速度。
啟動速度,一直在我們的 App 優(yōu)化清單上,而在 11 月舉辦的 Android 綠色聯(lián)盟開發(fā)者大會上,推出了應(yīng)用體驗(yàn)標(biāo)準(zhǔn)。對應(yīng)用的兼容性、穩(wěn)定性、性能、功能和安全,都做了詳細(xì)的定義。
其中啟動速度做了更細(xì)致的要求,冷啟動 < 1s,熱啟動 < 0.5s。這當(dāng)然是最理想的情況,具體還有外部因素的影響,例如手機(jī)配置。
啟動時(shí)初始化的代碼,勢必會拖慢 App 的啟動速度,但是不等待這些任務(wù)初始化完成呢,可能又會造成功能的缺失,而有時(shí)候不同任務(wù)還存在時(shí)序依賴的關(guān)系,要求我們先執(zhí)行 A 任務(wù),再執(zhí)行 B 任務(wù)。
每次都特殊處理會增加復(fù)雜度,我們需要一套通用的解決方案。
這里給大家推薦一個(gè) Alibaba 在 Github 上開源的一個(gè) Alpha 的庫。它是一個(gè)基于 PERT 圖構(gòu)建的 Android 異步啟動框架。
Alibaba Alpha
PERT 圖又稱為“計(jì)劃評審技術(shù)”,它采用網(wǎng)絡(luò)圖來描述一個(gè)項(xiàng)目的任務(wù)網(wǎng)絡(luò)。不僅可以表達(dá)任務(wù)與任務(wù)之間的關(guān)系,不同的任務(wù)之間還可以有各種子任務(wù)。
Alpha 就是基于 PERT 圖設(shè)計(jì)思想,它簡單、高效、功能完整。利用 Alpha 在應(yīng)用啟動的時(shí)候,讓這些任務(wù)并發(fā)處理,從而達(dá)到提高啟動速度的目的。并且可以保證他們執(zhí)行順序的正確性。
Alpha 在使用時(shí),只需要定義好自己的 Task,并描述它依賴的 Task,再將他們添加到 Project 中??蚣軙詣硬l(fā)有序地執(zhí)行這些 Task,***將執(zhí)行結(jié)果拋出來。
為了支持 Android 應(yīng)用的多進(jìn)程,Alpha 支持為不同進(jìn)程配置不同的啟動模式。
Alpha 的接入非常簡單,它支持 Java 代碼和配置文件兩種方式來構(gòu)建一個(gè)啟動流程。
接入 Alpha
Gradle 依賴
- compile 'com.alibaba.android:alpha:1.0.0.1@jar'
使用 Gradle 可能會導(dǎo)致失敗,這里可以考慮通過源碼引入的方式。
使用指南
1. 實(shí)現(xiàn)自己的 Task 類
在 Alpha 中,任務(wù)都是一個(gè)個(gè) Task。定義一個(gè) Task,并在 run() 方法中實(shí)現(xiàn)該 Task 需要做的事情。
- public class SampleTask extends Task{
- public SampleTask() {
- super("SampleTask");
- }
- @Override
- public void run() {
- //do something, print a msg for example.
- Log.d(TAG, "run SampleTask");
- }
- }
Task 默認(rèn)是通過異步的方式在子線程中執(zhí)行,如果這個(gè) Task 需要在主線程中執(zhí)行,可以在構(gòu)造函數(shù)中指定。
- /**
- * 構(gòu)造{@code Task}對象。
- *
- * @param name {@code Task}名字
- * @param isInUiThread 是否在UI線程執(zhí)行,true表示在UI線程執(zhí)行,false表示在非UI線程執(zhí)行,默認(rèn)在非UI線程執(zhí)行。
- * <strong>注意:如果在UI線程執(zhí)行,則不能再使用{@link AlphaManager#waitUntilFinish()},否則會造成死鎖。</strong>
- */
- public Task(String name, boolean isInUiThread) {
- mName = name;
- mIsInUiThread = isInUiThread;
- }
2. 將 Task 組合成一個(gè)完整的 Project
可以用 Task.ProjectBuilder 依據(jù)各 Task 之間的依賴關(guān)系,將這些 Task 構(gòu)建成一個(gè)完整的 Project。
- private Task createCommonTaskGroup() {
- Task a = new TaskA();
- Task b = new TaskB();
- Task c = new TaskC();
- Task d = new TaskD();
- Task e = new TaskE();
- Project.Builder builder = new Project.Builder();
- builder.add(a);
- builder.add(b).after(a);
- builder.add(c).after(a);
- builder.add(d).after(b, c);
- builder.add(e).after(a);
- Project group = builder.create();
- return group;
- }
ProjectBuilder 生成的 Project 本身又可以作為一個(gè) Task 嵌入到另一個(gè) Project 中。
- private Task createCommonTaskGroup() {
- Task a = new TaskA();
- Task b = new TaskB();
- Task c = new TaskC();
- Task d = new TaskD();
- Task e = new TaskE();
- Project.Builder builder = new Project.Builder();
- builder.add(a);
- builder.add(b).after(a);
- builder.add(c).after(a);
- builder.add(d).after(b, c);
- builder.add(e).after(a);
- Project group = builder.create();
- return group;
- }
- private void createProject() {
- Task group = createCommonTaskGroup();
- Task f = new TaskF();
- Project.Builder builder = new Project.Builder();
- builder.add(group);
- builder.add(f);
- Project project = builder.create();
- }
3. 監(jiān)聽 Task 執(zhí)行結(jié)束
可以通過 addOnTaskFinishListener() 監(jiān)聽 Task 的執(zhí)行結(jié)束。
- /**
- * <p>增加{@code Task}執(zhí)行結(jié)束的監(jiān)聽,當(dāng)該{@code Task}執(zhí)行結(jié)束時(shí),會回調(diào)
- * {@link Task.OnTaskFinishListener#onTaskFinish(String)}。</p>
- * <strong>注意:</strong>回調(diào)函數(shù)在{@code Task}所在線程中回調(diào),注意線程安全。
- *
- * @param listener 監(jiān)聽{@code Task}執(zhí)行結(jié)束的{@code listener}
- */
- public void addOnTaskFinishListener(OnTaskFinishListener listener) {
- if (!mTaskFinishListeners.contains(listener)) {
- mTaskFinishListeners.add(listener);
- }
- }
4. 為構(gòu)建完成的 Project 配置對應(yīng)的進(jìn)程
通過 addProject(),將 Project 配置到對應(yīng)的進(jìn)程中。
- AlphaManager.getInstance(mContext)
- .addProject(project);
5. 執(zhí)行啟動流程
***只需要調(diào)用一句 start() 方法,就可以執(zhí)行這個(gè)完整的流程了。
- AlphaManager.getInstance(mContext)
- .start();
Alpha 還提供了配置文件的方式來配置 Task 的關(guān)系,但是我不準(zhǔn)備再詳細(xì)介紹了,反正我不會這么用,有興趣還是去查詢 README 文件吧。
小結(jié)
利用 Alpha 我們可以有效的管理啟動時(shí)初始化的一些任務(wù),從而達(dá)到優(yōu)化啟動速度的目的。
Alpha 是 Alibaba 開源的,現(xiàn)在我還不確定用在了那些阿里系的商業(yè)項(xiàng)目上,不過從源碼的角度來看,沒有大坑,而且各自文檔也很齊全,如果有這方面的需求,可以嘗試使用。
【本文為51CTO專欄作者“張旸”的原創(chuàng)稿件,轉(zhuǎn)載請通過微信公眾號聯(lián)系作者獲取授權(quán)】