Android 性能優化工具 TraceView 簡單使用

背景android

最近產品以及測試大佬反應快搜桌面進入搜索頁面跳轉較爲緩慢,影響體驗,爲了優化這個問題,特意學習Android 性能優化工具 TraceView的 簡單使用,這纔有了本文。性能優化

正文bash

以下圖打開android device monitor ,打開有點慢,請耐心等待:app


可能有些同窗會打不開,出現以下的錯誤:ide


重裝一遍jdk,配好環境變量通常就沒有問題了。android device monitor打開以後如圖:函數


能夠看到TraceView 集成了不少小工具,圖上標紅的1是個截取設備當前屏幕的工具,做爲和測試後臺交(si)流(bi)的神器,能作到有圖有真相;圖上標紅的2因爲展現當前頁面視圖層級結構,以下圖:工具


能夠看到右邊上半部分能夠很清晰看到當前頁面視圖的結構,下半部分顯示的是選擇的視圖的一些信息,如位置信息等,這個工具的應用場景仍是很普遍的,好比產品大佬叫你改一個view的文本,有了這個工具你能夠很快定位到要改的是哪一個,上圖左邊還有好多小工具,這些不是本次的重點,有機會再說,不得不說一句,Google 大法好!!post

言歸正傳,選中你要分析的進程,如圖:性能


紅色1表示的位置由原來的灰色不可用的狀態變爲可用狀態,敲黑板啦,重點來了。這個按鈕叫 start method profiling(開始方法分析),點擊以後如圖:學習


點擊OK,會對接下來的操做進行跟蹤分析,這裏我點擊了跳轉搜索頁面的操做,而後在點擊剛剛那個按鈕,注意到按鈕變成了 stop method profiling(中止方法分析),稍等一下就有分析結果視圖以下:


先簡單介紹下這個視圖,紅色1主要表示當前選中方法調用的線程信息,紅色2表示的的是時間線,當你點擊紅色3區域的時候,時間線視圖會有相應的反饋,出現一個U型閃動,U型寬度就是方法的執行時間,能夠將藉助鼠標測量耗時,如圖先放到起點:


注意紅線部分表示當前時間,再把鼠標放到U型的結束位置,以下圖:


二者相減就能知道方法耗時,其實這個功能有點雞肋,通常不用,接下來我會介紹紅色3區域的功能,更加方便:


能夠看到這是個表格,表明的含義以下:

列名 含義
Name
該線程運行過程當中所調用的函數名
Incl Cpu Time
某函數佔用的CPU時間,包含內部調用其它函數的CPU時間
Excl Cpu Time
某函數佔用的CPU時間,但不含內部調用其它函數所佔用的CPU時間
Incl Real Time
某函數運行的真實時間(以毫秒爲單位),不含調用其它函數所佔用的真實時間
Excl Real Time
某函數運行的真實時間(以毫秒爲單位),不含調用其它函數所佔用的真實時間
Call+Recur Calls/Total
某函數被調用次數以及遞歸調用佔總調用次數的百分比
Cpu Time/Call
某函數調用CPU時間與調用次數的比。至關於該函數平均執行時間
Real Time/Call
同CPU Time/Call相似,只不過統計單位換成了真實時間

隨便點擊一個函數,Parent表示調用該方法的方法,Children表示該方法調用的方法 ,以下:


能夠看到LauncherSearchActvity的oncreate方法耗時1006.735這個很不正常,再找到Children裏面耗時最多的setContenView,一步步下去,最後定位到以下的位置:


能夠看到是KeybordLayout中initView()方法,繼續如圖:


能夠看到有些函數被重複調用了屢次,接下來就是分析優化這個方法了,先看下LauncherSearchActvity的界面:


左邊的區域是KeybordLayout在initView()進行鍵碼的初始化以下:

for (int i = 0; i < 6; i++) {
    for (int j = 0; j < 6; j++) {
        GonTextView mButton = new GonTextView(getContext());
        mButton.setFocusable(true);
        mButton.setGravity(Gravity.CENTER);
        if (j == 5) {
            mButton.setOnKeyListener(this);
            mButton.setTag(RIGHT_ROW_TAG);
        } else if (j == 0) {
            mButton.setId(DEFAULT_FOCUS_VIEW_ID);
        }
        mButton.getPaint().setFakeBoldText(true);
        mButton.setText(text_str[i][j]);
        ImageUtils.setBackground(mButton, R.drawable.sel_search_keyboard_item_solid);
        mButton.setTextColor(ResUtil.getColorList(isKeyboardNum(text_str[i][j]) ? R.color.sel_color_search_keyboard_item_123 : R.color.sel_color_search_keyboard_item_abc));
        keyboardAcherView.addView(mButton);

        //adapter
        mButton.setGonTextSize(38);
        mButton.setGonSize(70, 70);
        mButton.setGonMargin(j * (24 + 70), i * (24 + 70), 0, 0);

        // gain defualt focus item
        if (i == 0 && j == 0) {
            mButton.requestFocus();
        }
        mButton.setOnClickListener(v -> editText.append(((TextView) v).getText().toString()));
    }
}複製代碼

能夠看到36次循環,因此出現了上上張圖的Call+Recur Calls/Total中的值是36/36,這邊能夠簡單優化下,將鍵碼GonTextView 放到一個集合裏面,這步的操做放在子線程,而後在主線程遍歷,addView()就行了,代碼以下:

Observable.create((ObservableOnSubscribe<ArrayList<ViewWrapper>>) e -> {
            ArrayList<ViewWrapper> gonTextViews = initKeys();
            e.onNext(gonTextViews);
            e.onComplete();
        }).subscribeOn(RxCompat.getSchedulerOnDb())
                .observeOn(RxCompat.getSchedulerOnMain()).subscribe(new RxCompatObserver<ArrayList<ViewWrapper>>() {
            @Override
            public void onSubscribeCompat(Disposable d) {

            }

            @Override
            public void onNextCompat(ArrayList<ViewWrapper> gonTextViews) {
                GonRelativeLayout keyboardAcherView = (GonRelativeLayout) findViewById(R.id.ll_keys);
                keyboardAcherView.removeAllViews();

                for (ViewWrapper viewWrapper : gonTextViews) {
                    keyboardAcherView.addView(viewWrapper.gonTextView);
//                    keyboardAcherView.reqLa
                    //adapter
                    viewWrapper.gonTextView.setGonTextSize(38);
                    viewWrapper.gonTextView.setGonSize(70, 70);
                    viewWrapper.gonTextView.setGonMargin(viewWrapper.x * (24 + 70), viewWrapper.y * (24 + 70), 0, 0);
                    if (viewWrapper.x == 0 && viewWrapper.y == 0) {
                        viewWrapper.gonTextView.requestFocus();
                    }
                }
                setVisibility(VISIBLE);
                if (SpUtil.getBoolean(SpUtil.SpKey.IS_INPUT_METHOD, false)) {
                    postDelayed(() -> btnInputMethod.performClick(), 50);
                }
            }
        });
複製代碼
private ArrayList<ViewWrapper> initKeys() {
    ArrayList<ViewWrapper> gonTextViews = new ArrayList<>(36);
    String[][] text_str = new String[][]{
            {"A", "B", "C", "D", "E", "F"},
            {"G", "H", "I", "J", "K", "L"},
            {"M", "N", "O", "P", "Q", "R"},
            {"S", "T", "U", "V", "W", "X"},
            {"Y", "Z", "1", "2", "3", "4"},
            {"5", "6", "7", "8", "9", "0"}
    };
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 6; j++) {
            GonTextView mButton = new GonTextView(getContext());
            mButton.setFocusable(true);
            mButton.setGravity(Gravity.CENTER);
            if (j == 5) {
                mButton.setOnKeyListener(this);
                mButton.setTag(RIGHT_ROW_TAG);
            } else if (j == 0) {
                mButton.setId(DEFAULT_FOCUS_VIEW_ID);
            }
            mButton.getPaint().setFakeBoldText(true);
            mButton.setText(text_str[i][j]);
            ImageUtils.setBackground(mButton, R.drawable.sel_search_keyboard_item_solid);
            mButton.setTextColor(ResUtil.getColorList(isKeyboardNum(text_str[i][j]) ? R.color.sel_color_search_keyboard_item_123 : R.color.sel_color_search_keyboard_item_abc));
            gonTextViews.add(new ViewWrapper(i,j,mButton));


            mButton.setOnClickListener(v -> editText.append(((TextView) v).getText().toString()));
        }
    }
    return gonTextViews;
}複製代碼

結果如圖:


從原來的1000多毫秒到不到300毫秒,提高仍是很大的!

碼字不易,期待各位的讚揚!!!

    

相關文章
相關標籤/搜索