Android的布局優(yōu)化思想很簡單,就是盡可能減少布局文件的層級,布局層級少了意味著 Android 繪制時工作量少了,性能自然就提高了.因此,我們需要刪除布局中無用的層級和控件,要合理使用 LinearLayout 和 RelativeLayout ; LinearLayout 簡單高效, RelativeLayout 功能強大但耗費內存,我們應該如何選擇呢?
如果是一個 LinearLayout 和 RelativeLayout 都能完成的簡單布局那果斷是 LinearLayout .但現(xiàn)實往往不會這樣子,單純的 LinearLayout 是無法滿足產(chǎn)品的需求的,往往要多個 LinearLayout 進行嵌套才能完成,這情況就使用 RelativeLayout ;布局層級的增加對產(chǎn)品性能消耗遠比使用 RelativeLayout 要嚴重的多.
Android的布局優(yōu)化另一個重要手段就是使用 include , merge , ViewStub 這3個標簽來進行優(yōu)化.下面來介紹它們的使用方法:
1.重用布局include:
include標簽常用于將布局中的公共部分提取出來供其他layout共用,常用與toolbar或actionbar;
在布局文件中使用include標簽:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/toolbar"/>
...
</LinearLayout>
注:可以在include標簽中重寫include布局android:layout的相關屬性,但前提是將
android:layout_height和android:layout_width都要寫上,如:
<include layout="@layout/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/new_id"/>
2.減少布局層次merge:
merge標簽一般都是和include標簽配合使用,不過具體要怎么做呢?還是看代碼來了解吧.
這是app主體布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<include layout="@layout/include_item" />
</LinearLayout>
include_item的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_pic"
android:src="@mipmap/ic_launcher"
android:layout_width="300dp"
android:layout_height="300dp" />
</RelativeLayout>
此時可以使用hierarchy viewer看下app的層級視圖:

可以看到有一個RelativeLayout的層級
現(xiàn)在將include_item改成merge:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_pic"
android:src="@mipmap/ic_launcher"
android:layout_width="300dp"
android:layout_height="300dp" />
</merge>
在看繪圖布局:

可以看到,成功減少了一個布局層級;
3.高效占位符:ViewStub:
我們經(jīng)常會遇到這么個情況,運行時根據(jù)情況來決定顯示哪一個View或者布局;之前人們的做法往往時使用
View.Gone和View.Visitiable讓View或布局疊加在一起,然后在代碼中動態(tài)修改它們的可見性;
這樣做的優(yōu)點是邏輯簡單,控制靈活;缺點是耗費資源,xml代碼復雜,不利于閱讀
針對這個情況,ViewStub就出現(xiàn)了,這是一個輕量級的View,它是一個看不見,不占布局,耗費資源極小的一個控件;
那它應該如何使用呢?看代碼吧:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/subu_view"
android:layout="@layout/real_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
可以看到我們通過ViewStub的layout屬性來讓ViewStub指向了另一個布局real_view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_pic"
android:src="@mipmap/ic_launcher"
android:layout_width="300dp"
android:layout_height="300dp" />
</LinearLayout>
此時我們運行在手機上就只能看到空白一片,但只要我們設置下面的代碼:
findViewById(R.id.subu_view).setVisibility(View.VISIBLE);
或者是:
View pic = ((ViewStub)findViewById(R.id.subu_view)).inflate();
上面兩個方法都能展示ViewStub的內部布局,讓內部布局替換ViewStub,一旦執(zhí)行ViewStub就不再是當前布局的一部分了.如果我們還想找到ViewStub內部布局的控件,在使用第二個方法的前提下,可以這么做:
ImageView iv_pic = (ImageView) pic.findViewById(R.id.iv_pic);
搞明白用法后,那以后遇到要將兩個View或布局重疊的情況就可以使用兩個ViewStub了來疊加了
但是目前ViewStub有個缺陷,就是不支持merge布局;