抽象佈局——include、merge 、ViewStub
在佈局優化中,Androi的官方提到了這三種佈局<include />、<merge />、<ViewStub />,並介紹了這三種佈局各有的優勢,下面也是簡單說一下他們的優勢,以及怎麼使用,記下來權當做筆記。
1、佈局重用<include />
<include />標籤能夠重用佈局檔案,簡單的使用如下:
[html] view plain copy print?- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
-
android:orientation
- android:layout_width=”match_parent”
- android:layout_height=”match_parent”
- android:background="@color/app_bg"
- android:gravity="center_horizontal">
- <includelayout="@layout/titlebar"/>
- <TextViewandroid:layout_width=”match_parent”
-
android:layout_height
- android:text="@string/hello"
- android:padding="10dp"/>
- ...
- </LinearLayout>
1)<include />標籤可以使用單獨的layout屬性,這個也是必須使用的。
2)可以使用其他屬性。<include />標籤若指定了ID屬性,而你的layout也定義了ID,則你的layout的ID會被覆蓋,解決方案。
3)在include標籤中所有的都是有效的,前提是必須要寫layout_width
4)佈局中可以包含兩個相同的include標籤,引用時可以使用如下方法解決(參考):
[html] view plain copy print?- View bookmarks_container_2 = findViewById(R.id.bookmarks_favourite);
- bookmarks_container_2.findViewById(R.id.bookmarks_list);
2、減少檢視層級<merge />
<merge/>標籤在UI的結構優化中起著非常重要的作用,它可以刪減多餘的層級,優化UI。例如你的主佈局檔案是垂直佈局,引入了一個垂直佈局的include,這是如果include佈局使用的LinearLayout就沒意義了,使用的話反而減慢你的UI表現。這時可以使用<merge/>標籤優化。
[html] view plain copy print?- <mergexmlns:android="http://schemas.android.com/apk/res/android">
- <Button
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/add"/>
- <Button
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/delete"/>
- </merge>
注意:當merge所在佈局用於getLayoutInflater().inflate(R.layout.merge_item,
new LinearLayout(this), true);時,方法inflate()中引數root和attachToRoot必須賦值,且attachToRoot必須為true;
3、需要時使用<ViewStub />
<ViewStub />標籤最大的優點是當你需要時才會載入,使用他並不會影響UI初始化時的效能。
在開發應用程式的時候,經常會遇到這樣的情況,會在執行時動態根據條件來決定顯示哪個View或某個佈局。那麼最通常的想法就是把可能用到的View都寫在上面,先把它們的可見性都設為View.GONE,然後在程式碼中動態的更改它的可見性。這樣的做法的優點是邏輯簡單而且控制起來比較靈活。但是它的缺點就是,耗費資源。雖然把View的初始可見View.GONE但是在Inflate佈局的時候View仍然會被Inflate,也就是說仍然會建立物件,會被例項化,會被設定屬性。也就是說,會耗費記憶體等資源。
推薦的做法是使用Android.view.ViewStub,ViewStub是一個輕量級的View,它一個看不見的,不佔佈局位置,佔用資源非常小的控制元件。可以為ViewStub指定一個佈局,在Inflate佈局的時候,只有ViewStub會被初始化,然後當ViewStub被設定為可見的時候,或是呼叫了ViewStub.inflate()的時候,ViewStub所向的佈局就會被Inflate和例項化,然後ViewStub的佈局屬性都會傳給它所指向的佈局。這樣,就可以使用ViewStub來方便的在執行時,要還是不要顯示某個佈局。
首先來說說ViewStub的一些特點:
1. ViewStub只能Inflate一次,之後ViewStub物件會被置為空。按句話說,某個被ViewStub指定的佈局被Inflate後,就不會夠再通過ViewStub來控制它了。
2. ViewStub只能用來Inflate一個佈局檔案,而不是某個具體的View,當然也可以把View寫在某個佈局檔案中。
基於以上的特點,那麼可以考慮使用ViewStub的情況有:
1. 在程式的執行期間,某個佈局在Inflate後,就不會有變化,除非重新啟動。
因為ViewStub只能Inflate一次,之後會被置空,所以無法指望後面接著使用ViewStub來控制佈局。所以當需要在執行時不止一次的顯示和隱藏某個佈局,那麼ViewStub是做不到的。這時就只能使用View的可見性來控制了。
2. 想要控制顯示與隱藏的是一個佈局檔案,而非某個View。
因為設定給ViewStub的只能是某個佈局檔案的Id,所以無法讓它來控制某個View。
所以,如果想要控制某個View(如Button或TextView)的顯示與隱藏,或者想要在執行時不斷的顯示與隱藏某個佈局或View,只能使用View的可見性來控制。
總之:ViewStub小控制元件佔用記憶體小,比View.GONE更節省記憶體資源,缺點是隻能對佈局進行單次inflate顯示操作,
即只適合於需要佔用記憶體小,而在必要時顯示佈局的情況。
- <ViewStub
- android:id="@+id/stub_import"
- android:layout="@layout/progress_overlay"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"/>
android:layout=“”這裡是要替換的佈局檔案,佈局中的屬性要在ViewStub中設定,如android:layout_marginLeft="5dip";android:background=""等屬性設定。
當你想載入佈局時,可以使用下面其中一種方法:
[java] view plain copy print?- ((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
- // or
- View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
注:當呼叫inflate()函式的時候,ViewStub被引用的資源替代,並且返回引用的view,
但是顯示設定用android:visibility="visible"則不起作用。另外ViewStub目前有個缺陷就是還不支援 <merge />標籤。