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標籤的使用: