Android布局優(yōu)化之 - 復用、減少層級鹰贵、按需加載

本文針對include晴氨、merge、ViewStub三個標簽如何在布局復用碉输、有效減少布局層級以及如何可以按需加載三個方面進行介紹的籽前。
復用布局可以幫助我們創(chuàng)建一些可以重復使用的復雜布局。這種方式也意味著應用中任何在多個布局文件之間使用的通用布局都可以被提取出來,然后分別進行管理枝哄,使用的時候再進行組合肄梨。因此當我們在自定義一些View的時候,使用復用布局會更簡單方便挠锥。在平常開發(fā)中使用可以復用的布局文件众羡,不僅僅是因為它可以有效減少布局文件數(shù)量,更多的目的在于它更方面我們管理應用蓖租,布局復用粱侣,在更改某個組件時就可以做到改一個布局文件就更改了應用中所有引用該布局文件的組件,做到一改全改蓖宦。
<include/>
<include/>標簽在布局優(yōu)化中是使用最多的一個標簽了齐婴,它就是為了解決重復定義布局的問題。<include/>標簽就相當于C稠茂、C++中的include頭文件一樣柠偶,把一些常用的底層的API封裝起來,需要的時候引入即可主慰。在一些開源的J2EE中許多XML配置文件也都會使用<include/>標簽嚣州,將多個配置文件組合成為一個更為復雜的配置文件,如最常見的S2SH共螺。
在以前Android開發(fā)中该肴,由于ActionBar設計上的不統(tǒng)一以及兼容性問題,所以很多應用都自定義了一套自己的標題欄titlebar藐不。標題欄我們知道在應用的每個界面幾乎都會用到匀哄,在這里可以作為一個很好的示例來解釋<include/>標簽的使用。
下面是一個自定義的titlebar文件:
'<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/titlebar_bg"> <ImageViewandroid:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/gafricalogo"/></FrameLayout>'

在應用中使用titlebar布局文件雏蛮,我們通過<include/>標簽,布局文件如下:
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" 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="wrap_content" android:text="@string/hello" android:padding="10dp"/> ... </LinearLayout>

在<include/>標簽中可以覆蓋導入的布局文件root布局的布局屬性(如layout_*屬性)涎嚼。
布局示例如下:
<includeandroid:id="@+id/news_title" android:layout_width="match_parent" android:layout_height="match_parent" layout="@layout/title"/>

如果想使用<include/>標簽覆蓋嵌入布局root布局屬性,必須同時覆蓋layout_height和layout_width屬性挑秉,否則會直接報編譯時語法錯誤法梯。
Layout parameter layout_height ignored unless layout_width is also specified on <include> tag
如果<include/>標簽已經(jīng)定義了id,而嵌入布局文件的root布局文件也定義了id犀概,<include>標簽的id會覆蓋掉嵌入布局文件root的id立哑,如果include標簽沒有定義id則會使用嵌入文件root的id。
<merge/>
<merge/>標簽都是與<include/>標簽組合使用的姻灶,它的作用就是可以有效減少View樹的層次來優(yōu)化布局铛绰。
下面通過一個簡單的示例探討一下<merge/>標簽的使用,下面是嵌套布局的layout_text.xml文件:
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:text="Hello World!" android:layout_height="match_parent"/></LinearLayout>

一個線性布局中嵌套一個文本視圖产喉,主布局如下:
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_wrap" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include android:id="@+id/layout_import" android:layout_width="match_parent" android:layout_height="match_parent" layout="@layout/layout_text"/> </LinearLayout>

通過hierarchyviewer我們可以看到主布局View樹的部分層級結(jié)構(gòu)如下圖:


現(xiàn)在講嵌套布局跟布局標簽更改為<merge/>捂掰,merge_text.xml布局文件如下:
<mergexmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Hello World!"/> </merge>

然后將主布局<include/>標簽中的layout更改為merge_text.xml敢会,運行后重新截圖如下:


對比截圖就可以發(fā)現(xiàn)上面的四層結(jié)構(gòu),現(xiàn)在已經(jīng)是三層結(jié)構(gòu)了这嚣。當我們使用<merge/>標簽的時候鸥昏,系統(tǒng)會自動忽略merge層級,而把TextView直接放置與<include/>平級疤苹。
<merge/>標簽在使用的時候需要特別注意布局的類型互广,例如我的<merge/>標簽中包含的是一個LinearLayout布局視圖,布局中的元素是線性排列的卧土,如果嵌套進主布局時惫皱,include標簽父布局時FrameLayout,這種方式嵌套肯定會出問題的尤莺,merge中元素會按照FrameLayout布局方式顯示旅敷。所以在使用的時候,<merge/>標簽雖然可以減少布局層級颤霎,但是它的限制也不可小覷媳谁。
<merge/>只能作為XML布局的根標簽使用。當Inflate以<merge/>開頭的布局文件時友酱,必須指定一個父ViewGroup晴音,并且必須設定attachToRoot為true。
View android.view.LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)
root不可少缔杉,attachToRoot必須為true锤躁。
ViewStub
在開發(fā)過程中,經(jīng)常會遇到這樣一種情況或详,有些布局很復雜但是卻很少使用系羞。例如條目詳情、進度條標識或者未讀消息等霸琴,這些情況如果在一開始初始化椒振,雖然設置可見性 View.GONE ,但是在Inflate的時候View仍然會被Inflate,仍然會創(chuàng)建對象梧乘,由于這些布局又想到復雜澎迎,所以會很消耗系統(tǒng)資源。
ViewStub就是為了解決上面問題的选调,ViewStub是一個輕量級的View嗡善,它一個看不見的,不占布局位置学歧,占用資源非常小的控件。
定義ViewStub布局文件
下面是一個ViewStub布局文件:
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_wrap" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ViewStub android:id="@+id/stub_image" android:layout_width="match_parent" android:layout_height="wrap_content" android:inflatedId="@+id/image_import" android:layout="@layout/layout_image"/> <ViewStub android:id="@+id/stub_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:inflatedId="@+id/text_import" android:layout="@layout/layout_text"/> </LinearLayout>

layout_image.xml文件如下(layout_text.xml類似):
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/layout_image"> <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>

加載ViewStub布局文件
動態(tài)加載ViewStub所包含的布局文件有兩種方式各吨,方式一使用使用inflate()方法枝笨,方式二就是使用setVisibility(View.VISIBLE)袁铐。
示例java代碼如下:
private ViewStubviewStub; protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_main2); viewStub = (ViewStub) findViewById(R.id.stub_image); //viewStub.inflate();//方式一 viewStub.setVisibility(View.VISIBLE);//方式二 ImageViewimageView = (ImageView) findViewById(R.id.imageView); imageView.setImageResource(R.drawable.image);}

示例View層級截圖如下:


ViewStub一旦visible/inflated,它自己就不在是View試圖層級的一部分了。所以后面無法再使用ViewStub來控制布局横浑,填充布局root布局如果有id剔桨,則會默認被android:inflatedId所設置的id取代,如果沒有設置android:inflatedId徙融,則會直接使用填充布局id洒缀。
由于ViewStub這種使用后即可就置空的策略,所以當需要在運行時不止一次的顯示和隱藏某個布局欺冀,那么ViewStub是做不到的树绩。這時就只能使用View的可見性來控制了。
layout_相關(guān)屬性與include標簽相似隐轩,如果使用應該在ViewStub上面使用饺饭,否則使用在嵌套進來布局root上面無效。
ViewStub的另一個缺點就是目前還不支持merge標簽职车。
小結(jié)
Android布局優(yōu)化基本上就設計上面include瘫俊、merge、ViewStub三個標簽的使用悴灵。在平常開發(fā)中布局推薦使用RelativeLayout扛芽,它也可以有效減少布局層級嵌套。最后了將merge和include源碼附上积瞒,ViewStub就是一個View川尖,就不貼出來了溉跃。
Include源碼
/
** Exercise <include /> tag in XML files.*/public class Include extends Activity { @Override protected void onCreate(Bundleicicle) { super.onCreate(icicle); setContentView(R.layout.include_tag); }}

Merge源碼
/*** Exercise <merge /> tag in XML files.*/public class Merge extends Activity { private LinearLayoutmLayout; @Override protected void onCreate(Bundleicicle) { super.onCreate(icicle); mLayout = new LinearLayout(this); mLayout.setOrientation(LinearLayout.VERTICAL); LayoutInflater.from(this).inflate(R.layout.merge_tag, mLayout); setContentView(mLayout); } public ViewGroupgetLayout() { return mLayout; }}

來自: http://www.sunnyang.com/418.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末火邓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子颖御,更是在濱河造成了極大的恐慌银酬,老刑警劉巖嘲更,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異揩瞪,居然都是意外死亡赋朦,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門李破,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宠哄,“玉大人,你說我怎么就攤上這事嗤攻∶担” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵妇菱,是天一觀的道長承粤。 經(jīng)常有香客問我暴区,道長,這世上最難降的妖魔是什么辛臊? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任仙粱,我火速辦了婚禮,結(jié)果婚禮上彻舰,老公的妹妹穿的比我還像新娘伐割。我一直安慰自己,他們只是感情好刃唤,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布隔心。 她就那樣靜靜地躺著,像睡著了一般透揣。 火紅的嫁衣襯著肌膚如雪济炎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天辐真,我揣著相機與錄音须尚,去河邊找鬼。 笑死侍咱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的楔脯。 我是一名探鬼主播撩轰,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼昧廷!你這毒婦竟也來了堪嫂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤木柬,失蹤者是張志新(化名)和其女友劉穎皆串,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眉枕,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡恶复,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了速挑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谤牡。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖姥宝,靈堂內(nèi)的尸體忽然破棺而出翅萤,到底是詐尸還是另有隱情,我是刑警寧澤腊满,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布断序,位于F島的核電站流纹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏违诗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一疮蹦、第九天 我趴在偏房一處隱蔽的房頂上張望诸迟。 院中可真熱鬧,春花似錦愕乎、人聲如沸阵苇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绅项。三九已至,卻和暖如春比肄,著一層夾襖步出監(jiān)牢的瞬間快耿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工芳绩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留掀亥,地道東北人。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓妥色,卻偏偏與公主長得像搪花,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嘹害,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容