溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

merge、include、ViewStub的作用及分析

發(fā)布時(shí)間:2020-09-03 20:46:36 來(lái)源:網(wǎng)絡(luò) 閱讀:2126 作者:一劍圍城 欄目:移動(dòng)開發(fā)

include:
方便復(fù)雜布局的重用,使得布局模塊化。最常使用到的地方如在每個(gè)Activity中加入統(tǒng)一的狀態(tài)欄。

merge:
減少include之后的布局層級(jí)。

ViewStub:
提高布局初次加載性能。常用于網(wǎng)絡(luò)加載失敗頁(yè),按需加載View等。

include、merge結(jié)合使用:
官方對(duì)<merge />的介紹中使用vertical的LinearLayout。當(dāng)需要include的Layout也是vertical的LinearLayout時(shí),會(huì)出現(xiàn)兩個(gè)vertical的LinearLayout相互嵌套的情況,這除了降低UI性能之外沒(méi)有其他作用。這時(shí)候可以把需要include的Layout的LinearLayout換成<merge />標(biāo)簽。這樣在編譯完成后TextView和兩個(gè)Button就是同級(jí)的,不會(huì)再多一層。

注意:在include中如果需要重寫layout_xxx屬性,則必須同時(shí)重寫layout_width和Layout_height。

<LinearLayout xmlns: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">

    <include layout="@layout/titlebar"/>

    <TextView 
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="@string/hello"
              android:padding="10dp" />
</LinearLayout>

需要include的layout:
這里的LinearLayout和TextView同一層級(jí)。兩個(gè)Button是其下一層子View。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal">

    <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"/>

</LinearLayout>

把root視圖LinearLayout換成merge:
這里兩個(gè)Button和TextView同一層級(jí),LinearLayout在include后已經(jīng)不存在了。

<merge xmlns: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適用于哪些布局類型:
試驗(yàn)后<merge />適用于我們常用的FrameLayout、LinearLayout、RelativeLayout等。但從官方的介紹中只見到FrameLayout和相同orientation的LinearLayout。因?yàn)檫@兩種情況下需要的include的View和原布局沒(méi)有耦合性,也就是沒(méi)關(guān)系。
而RelativeLayout使用<merge />需要知道兩者布局的情況,比如toRightof的對(duì)象是誰(shuí)等,這反而增加了兩個(gè)布局之間的耦合性,而include的作用不就是解耦合么。故此,RelativeLayout不適用。
而如果只用到centerInParent、alignParentTop之類的RelativeLayout的屬性,面對(duì)這種低程度的耦合,merge似乎還行。但這時(shí)候通??梢钥紤]更優(yōu)的方案了。

對(duì)于FrameLayout來(lái)說(shuō),無(wú)論嵌套多少層,顯示效果是一樣的,但UI性能更差,對(duì)于相同orientation的LinearLayout來(lái)說(shuō),嵌套多層,顯示效果也是一樣的,但UI性能也是更差。

The <merge /> tag helps eliminate redundant view groups in your view hierarchy when including one layout within another.
譯:merge標(biāo)簽幫助消除在一個(gè)布局中include進(jìn)另外一個(gè)布局后,造成的View層級(jí)中冗余的view groups。

為什么會(huì)造成冗余:
之所以會(huì)造成View層級(jí)的冗余嵌套,是因?yàn)橄到y(tǒng)規(guī)定了每一個(gè)獨(dú)立的布局文件都必須只有一個(gè)root view。而這個(gè)root view與內(nèi)部的子View不一定存在必須的關(guān)系(例如,引用root view的id的情況),可能只是提供一個(gè)父布局讓子類的layout_width等layout_xxxxx屬性起作用而已。這個(gè)作用可以由include后的再上一層布局提供。這時(shí)root view就沒(méi)用了。

代碼中加載根標(biāo)簽為merge的布局文件:
由于merge在加載后就不存在了。就好像岳父拉著女朋友的手交給你,他就走了。這個(gè)過(guò)程是在inflate中完成的。而merge在子view找到新parent后就安心離開,如果沒(méi)找到就不會(huì)放手,可憐×××。所以我們需要使用三個(gè)參數(shù)的inflate方法,在inflate的時(shí)候就指定新的parent,并attach。而root不需要再addView。
LayoutInflater.from(this).inflate(R.layout.titlebar, root, true);
不然會(huì)報(bào)錯(cuò):
<merge /> can be used only with a valid ViewGroup root and attachToRoot=true.

tools:showIn="@layout/activity_main"
在merge標(biāo)簽中加入此屬性,方便在編輯時(shí)查看本Layout在布局activity_main中include完成后的模樣,所見即所得,方便修改。

ViewStub如何提高加載性能:
對(duì)于一般的View來(lái)說(shuō),只要在布局文件中聲明了,那么在加載布局文件的時(shí)候,該View就會(huì)被加載進(jìn)內(nèi)存。并非布局中所有的View在首次加載時(shí)都需要,可以把首次不需要的放在ViewStub中。
ViewStub是一個(gè)不可見的、寬高為0、draw方法為空的輕量級(jí)的View,用于在運(yùn)行時(shí)再加載指定布局資源從而優(yōu)化布局加載速度。只有當(dāng)setVisibility(Visible/InVisible)或inflate()方法被調(diào)用,才會(huì)加載布局資源替換自身在父布局中的位置,并使用ViewStub的布局參數(shù)。

ViewStub和include的對(duì)比:
都是用于引入其他的布局,和直接在布局文件中寫入View相比,使用include的方式?jīng)]有性能上的優(yōu)勢(shì),反而可能降低性能。而使用ViewStub則能提高加載性能,例如,把一個(gè)復(fù)雜布局放在ViewStub中加載,則在該復(fù)雜布局不需要加載的時(shí)候,開銷變成了加載ViewStub的輕量開銷。

ViewStub注意:
1、ViewStub只能被加載一次,然后被inflate的layout所替換掉
2、不支持<merge />標(biāo)簽

不要使用ViewStub的對(duì)象,使用inflate返回的布局對(duì)象:

if (inflatedView == null) {
      ViewStub viewStub = findViewById(R.id.stub);
      inflatedView = viewStub.inflate();
}
TextView text = inflatedView.findViewById(R.id.text);
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI