1. 程式人生 > >Android的UI優化之merge、include、ViewStub標籤的使用

Android的UI優化之merge、include、ViewStub標籤的使用

最近要對新接手的一個Android專案做效能優化,經過大量的查閱學習,總結了一些知識點,特此記錄。此篇記錄UI效能方面的優化思路。

說起UI的優化,不得不瞭解一下過度繪製的概念、產生原因和表現、檢視以及優化overdraw的方法。 1. 過度繪製(Overdraw)概念 是指在一幀的時間(16.67ms)內,畫素被多次繪製 2. 產生的原因和表現 一個畫素被繪製一次是最理想的狀態,但是實際情況中,由於重疊的佈局導致一些畫素被多次繪製,每次繪製都是CPU的一組繪圖命令和GPU的一些操作,在單次繪製的時長超過16ms時,便會出現掉幀現象,也就是卡頓。 3. 如何檢視 Android系統是為我們提供了測量overdraw的功能的,開啟步驟:開發者選項=>除錯GPU過度繪製(show GPU overdraw),開啟之後便可以檢視目標頁面的overdraw狀態了。打開了之後系統提供了四種不同的顏色來繪製螢幕,用來指示overdraw的位置和程度:①沒有顏色:沒有發生overdraw,畫素只被繪製一次。②藍色:區域畫素被繪製兩次。如果大片的藍色是可以接受的,如果整個螢幕都是藍色,便可以在佈局的時候減少一層。③綠色:區域畫素被繪製三次,如果出現綠色,雖然可以接受,但是也需要著手優化和減少。④淺紅:區域畫素被繪製4次,小範圍可以接受。⑤暗紅:區域畫素被繪製5次。當畫素被繪製5次及以上,就是錯誤的,儘快修復。 4. 優化overdraw的方法 優化overdraw的原則是儘量避免重複對不可見元素的繪製和儘量減少佈局層級。這個時候merge、ViewStub標籤便能派上用場了。

ViewStub

ViewStub:即高效佔位符。 應用場景:在前端開發中,經常是需要根據條件動態顯示或隱藏某個view或layout,常用的做法是先對目標View或者layout的可見屬性設定成View.GONE,就可以簡單靈活地控制顯示或者隱藏。但是,這樣會浪費資源,因為雖然View或者layout可見性是GONE,但是在inflate佈局的時候,目標View或layout依然會被inflate,進而建立物件、被例項化、設定屬性值。 這個時候,可以使用ViewStub標籤。ViewStub是一個輕量級的View,它一個看不見的,不佔佈局位置,佔用資源非常小的控制元件。使用時為ViewStub指定佈局,在頁面inflate時, 只有ViewStub會被初始化,然後當ViewStub被設定為可見的時候,或是呼叫了ViewStub.inflate()的時候,ViewStub所向的佈局才會被Inflate和例項化。使用程式碼示例:

佈局檔案:


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/bt_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="顯示ViewStub" /> <Button android:id="@+id/bt_change" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="更改ViewStub" /> <Button android:id="@+id/bt_hide" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="隱藏ViewStub" /> </LinearLayout> <!--通過ViewStub的自身id,找到控制元件並呼叫 ViewStub#inflate()之後就失效 inflatedId是在ViewStab#inflate()之後替換的View 的id layout是用來替換ViewStub的佈局--> <ViewStub android:id="@+id/view_stub_test" android:inflatedId="@+id/rl_item" android:layout="@layout/layout_item_list_database_prac" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>

activity中使用程式碼,貼出按鈕的點選事件程式碼:

switch (v.getId()) {
                case R.id.bt_show:
                    /****
                     * ViewStub 只能呼叫inflate()一次,
                     * 呼叫之後,會被從檢視樹中移除,所以進行判空
                     */
                    if (findViewById(R.id.view_stub_test) != null)
                        ((ViewStub) findViewById(R.id.view_stub_test)).inflate();
                    else {
                        /**
                         * ViewStub為空就是已經被載入,用ViewStub的inflatedId屬性查詢替換佈局
                         */
                        findViewById(R.id.rl_item).setVisibility(View.VISIBLE);
                    }
                    break;
                case R.id.bt_change:
                    if (!findViewById(R.id.rl_item).isShown()) {
                        return;
                    }
                    i = ++i;
                    ((TextView) findViewById(R.id.text_layout_item_data_base_recycler)).setText("change" + (i));
                    break;
                case R.id.bt_hide:
                    if (findViewById(R.id.rl_item) == null)
                        return;
                    findViewById(R.id.rl_item).setVisibility(View.GONE);
                    break;
            }

首次顯示頁面:

這裡寫圖片描述

點選 顯示ViewStub Button:

這裡寫圖片描述

點選 更改ViewStub Button:

這裡寫圖片描述

點選 隱藏ViewStub Button:

這裡寫圖片描述

至此,ViewStub標籤的使用介紹完畢,下面介紹merge標籤的使用: