某布局作為子布局被其他布局include時,使用merge當作該布局的頂節點,這樣在被引入時頂結點會自動被忽略,而將其子節點全部合并到主布局中。
比如,如果你有一個 Layout 是一個豎直方向的 LinearLayout,其中包含兩個連續的 View 可以在別的 Layout 中重用,那麼你會做一個 LinearLayout 來包含這兩個 View ,以便重用。不過,當使用另一個 LinearLayout 來嵌套這個可重用的 LinearLayout 時,這種嵌套 LinearLayout 的方式除了減慢你的 UI 效能外沒有任何意義。
為了避免這種情況,你可以用 元素來替代可重用 Layout 的根節點。例如:
| 12345678910 |
"http://schemas.android.com/apk/res/android"> android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/add"/> android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/delete"/> |
現在,當你要將這個 Layout 包含到另一個 Layout 中時(並且使用了 標籤),系統會直接把兩個 Button 放到 Layout 中,而不會有多餘的 Layout 被嵌套。
二 使用標籤重用Layout如果你的程式 UI 在不同地方重複使用某個 Layout,那本節教你如何建立高效的,可重用的 Layout 組件,並把它們“包含”到 UI Layout 中。
為了高效重用整個的 Layout,你可以使用 和 標籤把其他 Layout 嵌入當前 Layout。
三 按需載入視圖除了簡單的把一個 Layout 包含到另一個中,你可能還想在程式開始後,僅當你的 Layout 對使用者可見時才開始載入。
3.1 不需要立即載入的布局,設定為GONE,系統會跳過,不載入3.2 使用ViewStub 實現按需載入ViewStub 是一個輕量的視圖,不需要大小資訊,也不會在被加入的 Layout 中繪製任何東西。每個 ViewStub 只需要設定 android:layout 屬性來指定需要被 inflate 的 Layout 類型。viewstub常用來引入那些預設不會顯示,只在特殊情況下顯示的布局,如進度布局、網路失敗顯示的重新整理布局、資訊出錯出現的提示布局等。
以下 ViewStub 是一個半透明的進度條覆蓋層。功能上講,它應該只在新的資料項目被匯入到應用程式時可見。
| 1234567 |
android:id="@+id/stub_import" android:inflatedId="@+id/panel_import" android:layout="@layout/progress_overlay" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" /> |
載入 ViewStub
當你要載入用 ViewStub 聲明的 Layout 時,要麼用 setVisibility(View.VISIBLE) 設定它的可見度,要麼調用其 inflate() 方法。
下面以在一個布局main.xml中加入網路錯誤時的提示頁面network_error.xml為例。main.mxl代碼如下:
| 1234567891011 |
"1.0" encoding="utf-8"?>"http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > …… android:id="@+id/network_error_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout="@layout/network_error" /> |
其中network_error.xml為只有在網路錯誤時才需要顯示的布局
setVisibility(View.VISIBLE)方式
| 123 |
View viewStub = ((ViewStub)findViewById(R.id.stub_import));viewStub.setVisibility(View.VISIBLE);netErrorLayout = findViewById(R.id.net_error_layout)) |
inflate方式
| 1 |
View netErrorLayout = ((ViewStub) findViewById(R.id.net_error_layout)).inflate(); |
注意:
inflate() 方法會在渲染完成後返回給被 inflate 的視圖,所以你不需要再調用 findViewById() 去尋找這個元素。減少inflate的次數,也會對效率有一點提升。
而setVisible方式還需要再次findViewById找到ViewStub中的元素。
一旦 ViewStub 可見或是被 inflate 了,ViewStub 元素就不存在了。取而代之的是被 inflate 的 Layout,其 id 是 ViewStub 上的 android:inflatedId 屬性。(ViewStub 的 android:id 屬性僅在 ViewStub 可見以前可用)
注意:ViewStub 的一個缺陷是,它目前不支援使用 標籤的 Layout
四 ListView的最佳化如果你有一個包含複雜或者每個項 (item) 包含很多資料的 ListView ,那麼上下滾動的效能可能會降低。本節給你一些關於如何把滾動變得更流暢的提示。
保持程式流暢的關鍵,是讓主線程(UI 線程)不要進行大量運算。你要確保在其他線程執行磁碟讀寫、網路讀寫或是 SQL 操作等。為了測試你的應用的狀態,你可以啟用 StrictMode。
4.1 使用後台線程你應該把主線程中的耗時間的操作,提取到一個後台線程中,使得主線程只關注 UI 繪畫。
4.2 在 View Holder 中填入視圖對象使用convertView、
你的代碼可能在 ListView 滑動時經常使用 findViewById(),這樣會降低效能。即使是 Adapter 返回一個用於回收的 convertView,你仍然需要尋找這個元素並更新它。避免頻繁調用 findViewById() 的方法之一,就是使用 View Holder(視圖預留位置)設計模式。
ViewHolder 儲存了標籤下的每個視圖。這樣你不用頻繁尋找這個元素:
| 1234567 |
static class ViewHolder { TextView text; TextView timestamp; ImageView icon; ProgressBar progress; int position;} |
然後,在 Layout 的類中產生一個 ViewHolder 對象:
| 1234 |
ViewHolder holder = new ViewHolder();holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);...convertView.setTag(holder); |
這樣你就可以輕鬆擷取每個視圖,而不是用 findViewById() 來不斷查詢檢視表,節省了寶貴的運算時間。
4.3 getView不要做複雜的操作因為每一條Item移入螢幕的時候,都會調用getView,不要在getView中做複雜的操作,不要頻繁的建立對象。Item點擊的處理不要提前做。特別是在快速滑動的時候,會導致頻繁的調用getView。
五 最佳化提示盡量使用RelativeLayout,可以減少層級的嵌套。
慎用LinearLayout的layout_weight屬性,可以使用RelativeLayout的centerHorizontal=”true”、toLeft、toRight代替
六 書寫規範上的最佳化6.1 Id的命名為了便於識別,你可以根據自己的業務來對當前介面的資源進行命名,比如當前是登陸介面,那麼你可以這樣命名:
login_edit_username
login_edit_password
login_btn_submit
login_txv_forgot_pass
6.2 資源的命名ic_action_add, ic_action_location (ActionBar Icons)
ic_play, ic_save (General Icons)
ic_tab_music, ic_tab_more (Tab Icons)
6.3 通用的資源命名對style.xml和dimens.xml的命名可以通用的盡量通用,因為一個項目的基本視圖很多都是通用的,比如ActionBar、ListView等,規範通用的命名可以很方便的移植到其它項目中。
| 12345678910 |
"list_item_large">#FCA558"list_item_small">#FBA228"list_item_large">24dp"list_item_small">18dp |