Android布局優(yōu)化:include 、merge道逗、ViewStub的詳細(xì)總結(jié)

一兵罢、include的用法以及注意點(diǎn)

在開發(fā)Android布局時,我們常將一些通用的視圖提取到一個單獨(dú)的layout文件中滓窍,然后使用<include>標(biāo)簽在需要使用的其他layout布局文件中加載進(jìn)來卖词,比如我們自己App導(dǎo)航欄等。這樣吏夯,便于對相同視圖內(nèi)容進(jìn)行統(tǒng)一的控制管理此蜈,提高布局重用性。

下面我們以大部分項(xiàng)目中都有的頭部導(dǎo)航欄為例噪生,說明一下include的使用裆赵,比如我們項(xiàng)目自己統(tǒng)一頭部導(dǎo)航欄,抽取布局如下:

titlebar.xml:

<?xml version="1.0"encoding="utf-8"?>

????android:layout_width="match_parent"

????android:layout_height="match_parent" >


?????<Button??

????????android:id="@+id/back"??

????????android:layout_width="wrap_content"??

????????android:layout_height="wrap_content"??

????????android:layout_alignParentLeft="true"??

????????android:layout_centerVertical="true"??

????????android:text="返回按鈕" />??

????<TextView??

????????android:id="@+id/title"??

????????android:layout_width="wrap_content"??

????????android:layout_height="wrap_content"??

????????android:layout_centerInParent="true"??

????????android:text="提示文字"??

????????android:textSize="20sp" />??

????<Button??

????????android:id="@+id/close"??

????????android:layout_width="wrap_content"??

????????android:layout_height="wrap_content"??

????????android:layout_alignParentRight="true"??

????????android:layout_centerVertical="true"??

????????android:text="關(guān)閉按鈕" />??


很簡單跺嗽,就是左右各一個按鈕战授,中間是一個提示文字。使用也比較簡單桨嫁,如下:

activity_main.xml:

????xmlns:tools="http://schemas.android.com/tools"

????android:layout_width="match_parent"

????android:layout_height="match_parent"

????tools:context="${relativePackage}.${activityClass}" >

????<include

????????android:layout_width="match_parent"

????????android:layout_height="40dp"

????????layout="@layout/titlebar" />

????<Button

????????android:layout_width="wrap_content"

????????android:layout_height="wrap_content"

????????android:layout_centerHorizontal="true"

????????android:layout_centerVertical="true"

????????android:onClick="click"

????????android:text="點(diǎn)我陈醒。。瞧甩。" />

include標(biāo)簽使用還是很簡單的,主要通過layout屬性聲明要引入的布局即可弥鹦。運(yùn)行程序界面如下:

include標(biāo)簽使用注意點(diǎn):

1肚逸,標(biāo)簽當(dāng)中,可以重寫所有l(wèi)ayout屬性的彬坏,如上面include中指定的layout屬性將會覆蓋掉titlebar中指定的layout屬性朦促。

而非layout屬性則無法在標(biāo)簽當(dāng)中進(jìn)行覆寫。另外需要注意的是栓始,如果我們想要在標(biāo)簽當(dāng)中覆寫layout屬性务冕,

必須要將layout_width和layout_height這兩個屬性也進(jìn)行覆寫,否則覆寫效果將不會生效

2幻赚,一個xml布局文件有多個include標(biāo)簽需要設(shè)置ID,才能找到相應(yīng)子View的控件,否則只能找到第一個include的layout布局,以及該布局的控件禀忆。

3臊旭,如果我們給include所加載的layout布局的根容器設(shè)置了id屬性,也在include標(biāo)簽中設(shè)置了id屬性箩退,同時需要在代碼中獲取根容器的控件對象時离熏,最好將這兩個id設(shè)置相同的名稱!否則戴涝,可能獲取不到根容器對象滋戳,即為null。

二啥刻、merge的用法以及注意點(diǎn)

merge標(biāo)簽存在的意義是幫助include標(biāo)簽排除多余的一層ViewGroup容器奸鸯,減少view hierarchy的結(jié)構(gòu),提升UI渲染的性能可帽。include標(biāo)簽存在著一個不好的地方娄涩,可能會導(dǎo)致產(chǎn)生多余的布局嵌套。同樣通過一個小demo來說明:

比如項(xiàng)目中有一個公共的登錄按鈕布局蘑拯,如下:

login.xml:

<?xml version="1.0"encoding="utf-8"?>

????android:layout_width="match_parent"

????android:layout_height="wrap_content"

????android:orientation="vertical" >


?????<Button?

????????android:layout_width="match_parent"??

????????android:layout_height="wrap_content"??

????????android:layout_marginLeft="20dp"??

????????android:layout_marginRight="20dp"??

????????android:text="登錄按鈕" />??


很簡單钝满,就是一個登錄的Button。

項(xiàng)目中有登錄功能的UI界面如下:

activity_login.xml:

????xmlns:tools="http://schemas.android.com/tools"

????android:layout_width="match_parent"

????android:layout_height="match_parent"

????android:orientation="vertical"

????android:background="@android:color/holo_blue_light">

????<EditText???

????????android:layout_width="match_parent"??

????????android:layout_height="wrap_content"?

????????android:layout_marginLeft="20dp"??

????????android:layout_marginRight="20dp"??

????????android:layout_marginTop="40dp"??

????????android:hint="請輸入用戶名" />


????<include layout="@layout/login" />

同樣非常簡單申窘,運(yùn)行程序弯蚜,如下:

看起來沒什么問題,其實(shí)不知不覺中我們多嵌套了一層布局剃法。我們用工具查看一下此時布局結(jié)構(gòu):

除去系統(tǒng)布局碎捺,我們自己布局最外層是LinearLayout,然后兩個并列布局EditText與LinearLayout贷洲,在LinearLayout里面是Button登錄按鈕收厨。

其實(shí)這種情況下:在主界面中,<include>標(biāo)簽的parent ViewGroup與包含的layout根容器ViewGroup是相同的類型优构,這里都是LinearLayout诵叁,那么則可以將包含的layout根容器ViewGroup使用<merge>標(biāo)簽代替,從而減少一層ViewGroup的嵌套钦椭,提升UI渲染性能拧额。

這里我們把a(bǔ)ctivity_login.xml修改如下:

<?xml version="1.0"encoding="utf-8"?>

?????<Button?

????????android:layout_width="match_parent"??

????????android:layout_height="wrap_content"??

????????android:layout_marginLeft="20dp"??

????????android:layout_marginRight="20dp"??

????????android:text="登錄按鈕" />??


重新運(yùn)行程序UI和上面一樣效果,通過工具再次查看布局結(jié)構(gòu);

看到了吧彪腔,我們自己布局減少了一層嵌套侥锦,從而提升了UI的渲染速度。

merge標(biāo)簽使用注意點(diǎn):

1,根布局是FrameLayout且不需要設(shè)置background或padding等屬性,可以用merge代替,因?yàn)锳ctivity的ContentView父元素就是FrameLayout,所以可以用merge消除只剩一個.

2,因?yàn)閙erge標(biāo)簽并不是View,所以在通過LayoutInflate.inflate()方法渲染的時候,第二個參數(shù)必須指定一個父容器,且第三個參數(shù)必須為true,也就是必須為merge下的視圖指定一個父親節(jié)點(diǎn).由于merge不是View所以****對merge標(biāo)簽設(shè)置的所有屬性都是無效的.

LayoutInflate中源碼體現(xiàn):

publicViewinflate(XmlPullParser parser, @Nullable ViewGroup root,booleanattachToRoot){synchronized(mConstructorArgs) {? ? ? ? ? ? ? ? ? ? ? ? ...if(TAG_MERGE.equals(name)) {if(root ==null|| !attachToRoot) {thrownewInflateException("<merge /> can be used only with a valid "+"ViewGroup root and attachToRoot=true");? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? rInflate(parser, root, inflaterContext, attrs,false);? ? ? ? ? ? ? ? }? ? ? ? ? ? ...? ? ? ? }? ? }

3,merge標(biāo)簽必須使用在根布局德挣,并且ViewStub標(biāo)簽中的layout布局不能使用merge標(biāo)簽.

三恭垦、ViewStub的用法以及注意點(diǎn)

ViewStub也可以用來加載布局文件,但與include標(biāo)簽完全不同。ViewStub是一個不可見的View類番挺,用于在運(yùn)行時按需懶加載資源唠帝,只有在代碼中調(diào)用了viewStub.inflate()或者viewStub.setVisible(View.visible)方法時才內(nèi)容才變得可見。這里需要注意的一點(diǎn)是建芙,當(dāng)ViewStub被inflate到parent時没隘,ViewStub就被remove掉了,即當(dāng)前view hierarchy中不再存在ViewStub禁荸,而是使用對應(yīng)的layout視圖代替右蒲。

同樣我們通過一個小demo說明一下,比如我們需要保存一個用戶信息赶熟,用戶名是必須保存的瑰妄,但是其余信息是不必要的,這是其余信息就可以一開始不顯示出來映砖,用戶想輸入的時候在現(xiàn)實(shí)出來间坐。

其余信息布局如下:

otherinfo.xml:

<?xml version="1.0"encoding="utf-8"?>

????android:layout_width="match_parent"

????android:orientation="vertical"

????android:layout_height="wrap_content" >

????<EditText

????????android:id="@+id/weichat_id"

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:layout_marginLeft="20dp"

????????android:layout_marginRight="20dp"

????????android:layout_marginTop="10dp"

????????android:hint="請輸入微信號" />

????<EditText

????????android:id="@+id/address_id"

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:layout_marginLeft="20dp"

????????android:layout_marginRight="20dp"

????????android:layout_marginTop="10dp"

????????android:hint="請輸入家庭住址" />

很簡單,沒什么其余解釋的邑退,主界面布局如下:

activity_main.xml:

????xmlns:tools="http://schemas.android.com/tools"

????android:layout_width="match_parent"

????android:layout_height="match_parent"

????android:background="@android:color/holo_blue_light"

????android:orientation="vertical" >

????<EditText

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:layout_marginLeft="20dp"

????????android:layout_marginRight="20dp"

????????android:layout_marginTop="40dp"

????????android:hint="請輸入用戶名" />

????<ViewStub

????????android:id="@+id/viewstub"

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:layout="@layout/otherinfo" />

????<Button

????????android:layout_width="match_parent"

????????android:layout_height="wrap_content"

????????android:onClick="show"

????????android:layout_marginLeft="20dp"

????????android:layout_marginRight="20dp"

????????android:layout_marginTop="10dp"

????????android:text="顯示" />

其余信息界面通過ViewStub引入進(jìn)來竹宋,關(guān)于ViewStub主要屬性以及方法說明如下:

android:layout屬性

加載包含的layout布局文件;

android:inflatedId屬性

重寫包含的layout布局文件的根容器id地技;

inflate()方法

與setVisible(int)方法作用類似蜈七,都可以使內(nèi)容得以顯示,只是inflate()會返回一個View對象莫矗,避免了額外使用findViewById()方法獲取layout視圖對象飒硅。

activity中代碼如下:

publicvoidshow(View view){//ViewStub stub = ((ViewStub) findViewById(R.id.viewstub));if(stub!=null){? ? ? ? ? ? View stubView = stub.inflate();? ? ? ? ? ? EditText address = (EditText) stubView.findViewById(R.id.address_id);? ? ? ? ? ? ? EditText wechatId = (EditText) stubView.findViewById(R.id.weichat_id);? ? ? ? ? }? ? }

好了,運(yùn)行程序作谚,一開始如下:

點(diǎn)擊顯示按鈕三娩,UI如下:

ViewStub標(biāo)簽使用注意點(diǎn):

1,ViewStub標(biāo)簽不支持merge標(biāo)簽妹懒。因此這有可能導(dǎo)致加載出來的布局存在著多余的嵌套結(jié)構(gòu)雀监,具體如何去取舍就要根據(jù)各自的實(shí)際情況來決定了。

2眨唬,ViewStub的inflate只能被調(diào)用一次,第二次調(diào)用會拋出異常滔悉。

3,雖然ViewStub是不占用任何空間的单绑,但是每個布局都必須要指定layout_width和layout_height屬性,否則運(yùn)行就會報(bào)錯曹宴。

好了搂橙,以上就是個人對于include 、merge、ViewStub使用的總結(jié)区转,希望對你有用苔巨,即使已經(jīng)掌握,希望讀完此文能溫故知新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末废离,一起剝皮案震驚了整個濱河市侄泽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜻韭,老刑警劉巖悼尾,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肖方,居然都是意外死亡闺魏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門俯画,熙熙樓的掌柜王于貴愁眉苦臉地迎上來析桥,“玉大人,你說我怎么就攤上這事艰垂∨菡蹋” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵猜憎,是天一觀的道長娩怎。 經(jīng)常有香客問我,道長拉宗,這世上最難降的妖魔是什么峦树? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮旦事,結(jié)果婚禮上魁巩,老公的妹妹穿的比我還像新娘。我一直安慰自己姐浮,他們只是感情好谷遂,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卖鲤,像睡著了一般肾扰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛋逾,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天茁瘦,我揣著相機(jī)與錄音撒遣,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛淡喜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼欺旧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蛤签,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤辞友,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后震肮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體称龙,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年钙蒙,在試婚紗的時候發(fā)現(xiàn)自己被綠了茵瀑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡躬厌,死狀恐怖马昨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扛施,我是刑警寧澤鸿捧,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站疙渣,受9級特大地震影響匙奴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妄荔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一泼菌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧啦租,春花似錦哗伯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恳蹲,卻和暖如春虐块,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘉蕾。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工贺奠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人错忱。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓儡率,卻偏偏與公主長得像颁糟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子喉悴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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