App體系化優化之啟動優化(一啟動時間分析)

2020-10-02 11:00:36

app的啟動模式分為三種:

1.冷啟動

冷啟動耗時最久,衡量的保準最多

Click Event - IPC - Process.start - ActivityThread - bindApplication - LifeCycle - ViewRootImpl

使用者在桌面點選app 發起一個IPC操作,通過Process.start 然後建立ActivityThread,是每一個單獨app程序的入口,訊息迴圈的建立,然後通過反射建立application呼叫於application相關的生命週期,最後就是建立我們常用的Activity的生命週期,當Activity的生命週期完畢後,就會進入到ViewRootImpl進行真正的介面繪製。

2.熱啟動

最簡單,最快

後臺 - 前臺

3.溫啟動

相對冷啟動比較快一些

LifeCycle

 

根據網際網路行業的8秒原則,我們需要控制冷啟動的啟動速度,那麼我們來看冷啟動都做了一些什麼呢?

冷啟動:

1.啟動app

2.載入空白頁(圖片替換)

3.建立程序

4.建立application

5.啟動出執行緒

6.建立MainActivity

7.載入佈局

8.佈置螢幕

9.首幀繪製

檢視啟動耗時:

方法1:

命令:adb命令觀察app啟動的時間  (線下使用,無法帶到線上)

adb shell am start -W -n 包名/類名   或者    adb shell am start -W 包名/類名

比如我自己的app:adb shell am start -W -n com.yinyan.ywf.app/com.cfs.app.ui.activity.sp.SpActivity

macdeMac-mini:~ mac$ adb shell am start -W -n com.yinyan.ywf.app/com.cfs.app.ui.activity.sp.SpActivity
Starting: Intent { cmp=com.yinyan.ywf.app/com.cfs.app.ui.activity.sp.SpActivity }
Status: ok
Activity: com.yinyan.ywf.app/com.cfs.app.ui.activity.sp.SpActivity
ThisTime: 2654  最後Activity啟動耗時
TotalTime: 2654 所有Activity啟動的耗時(包含閃屏)
WaitTime: 2673  AMS啟動Activity的總耗時
Complete

方法2:手動打點(線上捕獲)

/**
 * 啟動時間捕獲 手動打點
 */
public class LaunchTimer {

    private static long sTime;

    public static void startRecord(){
        sTime = System.currentTimeMillis();
    }

    public static void endRecord(){
        long cost = System.currentTimeMillis() - sTime;
        Logger.i("cost = ",cost);
    }
}

啟動時間記錄,在Application的attachBaseContext()方法中呼叫 LaunchTimer.startRecord()

結束的呼叫建議放在自己adapter的第一個item載入出來,或者activity渲染完畢的生命週期中,不要放在首幀回撥(onWindowFocusChanged)的位置,因為首幀回撥未必繪製完畢了頁面,是不準確的。

現在我們形成對比 我們先看看SophixApplitcation

 @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        LaunchTimer.startRecord();
//         如果需要使用MultiDex,需要在此處呼叫。
//         MultiDex.install(this);
        initSophix();
    }

接下來對比一下首幀繪製和FeedShow之後的啟動時間

IndexActivity

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        LaunchTimer.endRecord("onWindowFocusChanged");
        freshFragmnet();
    }
IndexActivity - HomeFragment - BusinessAdapter中的第一個Feed載入出來的時候

mHasRecorded自己宣告一下即可 布林型別

 @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
        Holder holder = (Holder) viewHolder;

        /**
         * 啟動首次繪製時間統計
         */
        if(position == 0 && !mHasRecorded){
            mHasRecorded = true;
            holder.ll_business.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    holder.ll_business.getViewTreeObserver().removeOnPreDrawListener(this);
                    LaunchTimer.endRecord("FeedShow");
                    return true;
                }
            });
        }
}