最新最準確內容建議直接訪問原文:Android性能優化之佈局優化java
本文爲Android性能優化的第二篇——佈局優化,主要介紹使用抽象佈局標籤(include, viewstub, merge)、去除沒必要要的嵌套和View節點、減小沒必要要的infalte及其餘Layout方面可調優勢,順帶說起佈局調優相關工具(hierarchy viewer和lint)。android
性能優化專題已完成五部分:算法
性能優化總綱——性能問題及性能調優方式
性能優化第三篇——Java(Android)代碼優化
性能優化第二篇——佈局優化
性能優化第一篇——數據庫性能優化數據庫
性能優化實例 緩存
一、抽象佈局標籤
(1) <include>標籤
include標籤經常使用於將佈局中的公共部分提取出來供其餘layout共用,以實現佈局模塊化,這在佈局編寫方便提供了大大的便利。
下面以在一個佈局main.xml中用include引入另外一個佈局foot.xml爲例。main.mxl代碼以下:性能優化
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/simple_list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="@dimen/dp_80" /> <include layout="@layout/foot.xml" /> </RelativeLayout>
其中include引入的foot.xml爲公用的頁面底部,代碼以下:網絡
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="@dimen/dp_40" android:layout_above="@+id/text"/> <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="@dimen/dp_40" android:layout_alignParentBottom="true" android:text="@string/app_name" /> </RelativeLayout>
<include>標籤惟一須要的屬性是layout屬性,指定須要包含的佈局文件。能夠定義android:id和android:layout_*屬性來覆蓋被引入佈局根節點的對應屬性值。注意從新定義android:id後,子佈局的頂結點i就變化了。app
(2) <viewstub>標籤
viewstub標籤同include標籤同樣能夠用來引入一個外部佈局,不一樣的是,viewstub引入的佈局默認不會擴張,即既不會佔用顯示也不會佔用位置,從而在解析layout時節省cpu和內存。
viewstub經常使用來引入那些默認不會顯示,只在特殊狀況下顯示的佈局,如進度佈局、網絡失敗顯示的刷新佈局、信息出錯出現的提示佈局等。
下面以在一個佈局main.xml中加入網絡錯誤時的提示頁面network_error.xml爲例。main.mxl代碼以下:模塊化
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > …… <ViewStub android:id="@+id/network_error_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout="@layout/network_error" /> </RelativeLayout>
其中network_error.xml爲只有在網絡錯誤時才須要顯示的佈局,默認不會被解析,示例代碼以下:工具
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/network_setting" android:layout_width="@dimen/dp_160" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="@string/network_setting" /> <Button android:id="@+id/network_refresh" android:layout_width="@dimen/dp_160" android:layout_height="wrap_content" android:layout_below="@+id/network_setting" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/dp_10" android:text="@string/network_refresh" /> </RelativeLayout>
在java中經過(ViewStub)findViewById(id)找到ViewStub,經過stub.inflate()展開ViewStub,而後獲得子View,以下:
private View networkErrorView; private void showNetError() { // not repeated infalte if (networkErrorView != null) { networkErrorView.setVisibility(View.VISIBLE); return; } ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout); networkErrorView = stub.inflate(); Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting); Button refresh = (Button)findViewById(R.id.network_refresh); } private void showNormal() { if (networkErrorView != null) { networkErrorView.setVisibility(View.GONE); } }
在上面showNetError()中展開了ViewStub,同時咱們對networkErrorView進行了保存,這樣下次不用繼續inflate。這就是後面第三部分提到的減小沒必要要的infalte。
viewstub標籤大部分屬性同include標籤相似。
上面展開ViewStub部分代碼
ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
networkErrorView = stub.inflate();
也能夠寫成下面的形式
View viewStub = findViewById(R.id.network_error_layout); viewStub.setVisibility(View.VISIBLE); // ViewStub被展開後的佈局所替換 networkErrorView = findViewById(R.id.network_error_layout); // 獲取展開後的佈局
效果一致,只是不用顯示的轉換爲ViewStub。經過viewstub的原理咱們能夠知道將一個view設置爲GONE不會被解析,從而提升layout解析速度,而VISIBLE和INVISIBLE這兩個可見性屬性會被正常解析。
(3) <merge>標籤
在使用了include後可能致使佈局嵌套過多,多餘沒必要要的layout節點,從而致使解析變慢,沒必要要的節點和嵌套可經過hierarchy viewer(下面佈局調優工具中有具體介紹)或設置->開發者選項->顯示佈局邊界查看。
merge標籤可用於兩種典型狀況:
a. 佈局頂結點是FrameLayout且不須要設置background或padding等屬性,能夠用merge代替,由於Activity內容試圖的parent view就是個FrameLayout,因此能夠用merge消除只剩一個。
b. 某佈局做爲子佈局被其餘佈局include時,使用merge看成該佈局的頂節點,這樣在被引入時頂結點會自動被忽略,而將其子節點所有合併到主佈局中。
以(1) <include>標籤的示例爲例,用hierarchy viewer查看main.xml佈局以下圖:
能夠發現多了一層不必的RelativeLayout,將foot.xml中RelativeLayout改成merge,以下:
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="@dimen/dp_40" android:layout_above="@+id/text"/> <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="@dimen/dp_40" android:layout_alignParentBottom="true" android:text="@string/app_name" /> </merge>
運行後再次用hierarchy viewer查看main.xml佈局以下圖:
這樣就不會有多餘的RelativeLayout節點了。
二、去除沒必要要的嵌套和View節點
更多調優方式及調優工具介紹見原文:Android性能優化之佈局優化
你可能還感興趣: