關(guān)于ViewStub的所有

ViewStub - Optimized Layout
  • 作用:用于優(yōu)化布局律姨,懶加載,運(yùn)行時(shí)才會(huì)加載布局臼疫。
  • 使用場(chǎng)景:通常用于有些隱藏的或者特殊情況才會(huì)顯示的布局择份。
    例如:一個(gè)ListView,數(shù)據(jù)為空時(shí),顯示一個(gè)布局告訴用戶

在xml中是使用:

<ViewStub
android:id="@+id/stub"
android:inflatedId="@+id/subTree"
android:layout="@layout/mySubTree"
/>

之前一直都不知道inflatedId有什么用烫堤,怎么用荣赶,決定看看源碼:

ViewStub的構(gòu)造器
super(context);
final TypedArray a = context.obtainStyledAttributes(attrs,
              R.styleable.ViewStub, defStyleAttr, defStyleRes);
mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);
mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
mID = a.getResourceId(R.styleable.ViewStub_id, NO_ID);
a.recycle();

setVisibility(GONE);
setWillNotDraw(true);

構(gòu)造很簡(jiǎn)單,讀取布局inflatedId, layout, id的屬性;調(diào)用setVisibility(GONE)鸽斟,所以ViewStub默認(rèn)是隱藏的拔创。
還有在實(shí)際使用中,會(huì)發(fā)現(xiàn)ViewStub除了
有inflatedId, layout富蓄, id這三個(gè)屬性剩燥,其他View的屬性都沒(méi)有效果。
原因是:ViewStub繼承View, 構(gòu)造器只是調(diào)用super(context),而在View中只有Content一個(gè)參數(shù)
的構(gòu)造器不會(huì)讀取其他屬性.

ViewStub的優(yōu)化原理簡(jiǎn)單粗暴, 重寫(xiě)onMeasure(), 測(cè)量時(shí)設(shè)置寬高為0格粪,重寫(xiě)draw()不繪制任何東西.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(0, 0);
}

@Override
public void draw(Canvas canvas) {
}

@Override
protected void dispatchDraw(Canvas canvas) {
}

看看inflate方法源碼:

public View inflate() {
        final ViewParent viewParent = getParent();
        if (viewParent != null && viewParent instanceof ViewGroup) {
            if (mLayoutResource != 0) {
                final ViewGroup parent = (ViewGroup) viewParent;
                final LayoutInflater factory;
                if (mInflater != null) {
                    factory = mInflater;
                } else {
                    factory = LayoutInflater.from(mContext);
                }
                final View view = factory.inflate(mLayoutResource, parent,
                        false);

                if (mInflatedId != NO_ID) {
                    view.setId(mInflatedId);
                }

                final int index = parent.indexOfChild(this);
                parent.removeViewInLayout(this);

                final ViewGroup.LayoutParams layoutParams = getLayoutParams();
                if (layoutParams != null) {
                    parent.addView(view, index, layoutParams);
                } else {
                    parent.addView(view, index);
                }

                mInflatedViewRef = new WeakReference<View>(view);

                if (mInflateListener != null) {
                    mInflateListener.onInflate(this, view);
                }

                return view;
            } else {
                throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
            }
        } else {
            throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
        }
    }

分析源碼得知:
首先調(diào)用getParent()獲取父布局parent躏吊,利用LayoutInflater把@layout/mySubTree這個(gè)layout加載,(為加載的layout起名為inflatedView),
把mInflatedId設(shè)置給inflatedView, int index = parent.indexOfChild(this)這一句獲取ViewStub在父布局的位置帐萎,
使用parent.removeViewInLayout(this)把ViewStub從parent中移除比伏,最后將inflatedView添加到相應(yīng)的位置并替換ViewStub.

使用ViewStub通常可以不用直接調(diào)用inflate(), 要顯示的時(shí)候直接可以調(diào)用setVisibility就可以了

public void setVisibility(int visibility) {
    if (mInflatedViewRef != null) {
        View view = mInflatedViewRef.get();
        if (view != null) {
            view.setVisibility(visibility);
        } else {
            throw new IllegalStateException("setVisibility called on un-referenced view");
        }
    } else {
        super.setVisibility(visibility);
        if (visibility == VISIBLE || visibility == INVISIBLE) {
            inflate();
        }
    }
}

mInflatedViewRef是一個(gè)View的弱引用疆导,調(diào)用inflate()后才不為null,
第一次調(diào)用setVisibility(VISIBLE||INVISIBLE)會(huì)調(diào)用inflate(),之后會(huì)從mInflatedViewRef中
獲取inflactedView的弱引用赁项,直接setVisibility(visibility).

還可以設(shè)置OnInflateListener這個(gè)接口進(jìn)行一些inflatedView的初始化工作,
這個(gè)接口只會(huì)被調(diào)用一次。
public static interface OnInflateListener {
void onInflate(ViewStub stub, View inflated);
}

注意事項(xiàng):

  1. inflate()方法只能調(diào)用一次澈段,由于第一次ViewStub已經(jīng)從parent中移除悠菜,parent第二次調(diào)用會(huì)為null,
    接著就會(huì)throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent")
  2. ViewStub在xml中id為stub败富,第一次使用findViewById()可以找到ViewStub悔醋,第二次之后就找不到了。
  3. 當(dāng)設(shè)置了android:inflatedId="@+id/subTree"兽叮,
    首次可以使用inflacte方法獲取inflactedView, View inflactedView = viewStub.inflacte(),
    接著可以findViewById(R.id.subTree)獲取inflactedView.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芬骄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鹦聪,更是在濱河造成了極大的恐慌账阻,老刑警劉巖略吨,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绪抛,死亡現(xiàn)場(chǎng)離奇詭異悼枢,居然都是意外死亡代乃,警方通過(guò)查閱死者的電腦和手機(jī)跨细,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)绒怨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蓝牲,“玉大人巡莹,你說(shuō)我怎么就攤上這事≡斐桑” “怎么了显熏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵雄嚣,是天一觀的道長(zhǎng)晒屎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)缓升,這世上最難降的妖魔是什么鼓鲁? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮港谊,結(jié)果婚禮上骇吭,老公的妹妹穿的比我還像新娘。我一直安慰自己歧寺,他們只是感情好燥狰,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著斜筐,像睡著了一般龙致。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上顷链,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天目代,我揣著相機(jī)與錄音,去河邊找鬼嗤练。 笑死榛了,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的煞抬。 我是一名探鬼主播霜大,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼革答!你這毒婦竟也來(lái)了战坤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蝗碎,失蹤者是張志新(化名)和其女友劉穎湖笨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蹦骑,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慈省,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片边败。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袱衷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出笑窜,到底是詐尸還是另有隱情致燥,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布排截,位于F島的核電站嫌蚤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏断傲。R本人自食惡果不足惜脱吱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望认罩。 院中可真熱鬧箱蝠,春花似錦、人聲如沸垦垂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)劫拗。三九已至间校,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杨幼,已是汗流浹背撇簿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留差购,地道東北人四瘫。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像欲逃,于是被迫代替她去往敵國(guó)和親找蜜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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