本篇文章爲Android優化的佈局部分,該部分應該是Android中很重要的,不管是在自定義控件中,仍是在簡單的書寫佈局時,都應該儘可能遵循一些優化原則,這樣佈局的繪製效率纔會更高,體驗才能更好。
java
Layout結構若是太複雜,Android的繪製過程就會很複雜,measure過程就會很複雜,我分析的View繪製機制中詳細介紹了整個測量、佈局和繪製過程,過於複雜、嵌套的佈局會形成性能問題。android
嵌套的 LinearLayout 可能會使得 View 的層級結構很深。使用LinearLayout時,一般咱們喜歡用嵌套的佈局來動態設置一個View的Visibility ,因爲LinearLayout是線性的,所以即便隱藏一個View也不會影響到其它View的排列。而在RelativeLayout中,View的位置都是相對於其它View的,所以,隱藏以後,會致使以前的View沒有參考對象了,致使的相對位置改變,這時你可使用alignWithParentIfMissing=」true」來處理這種狀況。git
此外,嵌套使用了 layout_weight 參數的 LinearLayout 的計算量會尤爲大,由於每一個子元素都須要被測量兩次。這對須要屢次重複 inflate 的 Layout 尤爲須要注意,好比使用 ListView 或 GridView 時。github
在使用了include後可能致使佈局嵌套過多,出現沒必要要的layout節點,從而致使解析變慢。設計模式
merge標籤可用於兩種典型狀況:api
好比,若是你有一個 Layout 是一個豎直方向的 LinearLayout,其中包含兩個連續的 View 能夠在別的 Layout 中重用,那麼你會作一個 LinearLayout 來包含這兩個 View ,以便重用。不過,當使用另外一個 LinearLayout 來嵌套這個可重用的 LinearLayout 時,這種嵌套 LinearLayout 的方式除了減慢你的 UI 性能外沒有任何意義。網絡
爲了不這種狀況,你能夠用
|
|
如今,當你要將這個 Layout 包含到另外一個 Layout 中時(而且使用了
若是你的程序 UI 在不一樣地方重複使用某個 Layout,那本節教你如何建立高效的,可重用的 Layout 部件,並把它們「包含」到 UI Layout 中。測試
爲了高效重用整個的 Layout,你可使用
除了簡單的把一個 Layout 包含到另外一箇中,你可能還想在程序開始後,僅當你的 Layout 對用戶可見時纔開始載入。
ViewStub 是一個輕量的視圖,不須要大小信息,也不會在被加入的 Layout 中繪製任何東西。每一個 ViewStub 只須要設置 android:layout 屬性來指定須要被 inflate 的 Layout 類型。viewstub經常使用來引入那些默認不會顯示,只在特殊狀況下顯示的佈局,如進度佈局、網絡失敗顯示的刷新佈局、信息出錯出現的提示佈局等。
如下 ViewStub 是一個半透明的進度條覆蓋層。功能上講,它應該只在新的數據項被導入到應用程序時可見。
|
|
載入 ViewStub
當你要載入用 ViewStub 聲明的 Layout 時,要麼用 setVisibility(View.VISIBLE) 設置它的可見性,要麼調用其 inflate() 方法。
下面以在一個佈局main.xml中加入網絡錯誤時的提示頁面network_error.xml爲例。main.mxl代碼以下:
|
|
其中network_error.xml爲只有在網絡錯誤時才須要顯示的佈局
setVisibility(View.VISIBLE)方式
|
|
inflate方式
|
|
注意:
inflate() 方法會在渲染完成後返回給被 inflate 的視圖,因此你不須要再調用 findViewById() 去查找這個元素。減小inflate的次數,也會對效率有一點提高。
而setVisible方式還須要再次findViewById找到ViewStub中的元素。
一旦 ViewStub 可見或是被 inflate 了,ViewStub 元素就不存在了。取而代之的是被 inflate 的 Layout,其 id 是 ViewStub 上的 android:inflatedId 屬性。(ViewStub 的 android:id 屬性僅在 ViewStub 可見之前可用)
注意:ViewStub 的一個缺陷是,它目前不支持使用
若是你有一個包含複雜或者每一個項 (item) 包含不少數據的 ListView ,那麼上下滾動的性能可能會下降。本節給你一些關於如何把滾動變得更流暢的提示。
保持程序流暢的關鍵,是讓主線程(UI 線程)不要進行大量運算。你要確保在其餘線程執行磁盤讀寫、網絡讀寫或是 SQL 操做等。爲了測試你的應用的狀態,你能夠啓用 StrictMode。
你應該把主線程中的耗時間的操做,提取到一個後臺線程中,使得主線程只關注 UI 繪畫。
使用convertView、
你的代碼可能在 ListView 滑動時常用 findViewById(),這樣會下降性能。即便是 Adapter 返回一個用於回收的 convertView,你仍然須要查找這個元素並更新它。避免頻繁調用 findViewById() 的方法之一,就是使用 View Holder(視圖佔位符)設計模式。
ViewHolder 存儲了標籤下的每一個視圖。這樣你不用頻繁查找這個元素:
|
|
而後,在 Layout 的類中生成一個 ViewHolder 對象:
|
|
這樣你就能夠輕鬆獲取每一個視圖,而不是用 findViewById() 來不斷查找視圖,節省了寶貴的運算時間。
由於每一條Item移入屏幕的時候,都會調用getView,不要在getView中作複雜的操做,不要頻繁的建立對象。Item點擊的處理不要提早作。特別是在快速滑動的時候,會致使頻繁的調用getView。
儘可能使用RelativeLayout,能夠減小層級的嵌套。
慎用LinearLayout的layout_weight屬性,可使用RelativeLayout的centerHorizontal=」true」、toLeft、toRight代替
爲了便於識別,你能夠根據本身的業務來對當前界面的資源進行命名,好比當前是登錄界面,那麼你能夠這樣命名:
login_edit_username
login_edit_password
login_btn_submit
login_txv_forgot_pass
ic_action_add, ic_action_location (ActionBar Icons)
ic_play, ic_save (General Icons)
ic_tab_music, ic_tab_more (Tab Icons)
對style.xml和dimens.xml的命名能夠通用的儘可能通用,由於一個項目的基本視圖不少都是通用的,好比ActionBar、ListView等,規範通用的命名能夠很方便的移植到其它項目中。
|
|