View Stub

5676 ワード

参照
        http://blog.csdn.net/hitlion2008/article/details/6737537。
概要
        View Stubは不可視であり、サイズが0の図では、運転時にレイアウトリソースを充填することができます。View Stubを視覚またはinflate()として設定すると、レイアウトリソースを充填し、View Stubを充填するビューが代替されます。
        ビューStubは、ビューの遅延負荷を実現するための優秀なクラスです。どのような状況でも、開発者がコンテキストによって非表示を選択したり、表示したりする必要があるなら、View Stubで実現できます。
一つのビューの遅延荷重によって性能が感じられないかもしれません。 明らかに向上していますが、ビューツリーの層が深いと、性能の差が感じられます。
        以上の2つは『Android開発に必要な50のコツ』から抜粋しました。
注意
        View Stubは一回だけです。
        レイアウトファイルでView Stubを使用する場合は、layout属性の値を指定しなければなりません。
        View Stubはinflate()によって指差されたレイアウトが父の配置に置き換えられます。
        それが指す配列のルート要素のいくつかのレイアウトパラメータは、<View Stub>に設定しなければならない。width,layout_heightなど
        「View Stub」のためのIDは、レイアウトファイルが生成するレイアウトのルート要素のIDに設定されます。
使用
        レイアウトにView Stubを使うのはとても簡単で、TextViewを使うのと同じです。しかし
layout属性を指定しなければなりません。属性はレイアウトファイルを指す必要があります。
        inflate Id属性を指定できます。この属性は、レイアウトファイルのルート要素を更新するためのIDです。(Overrides the id of the inflated View with th is value)。
        View Stubで作成した方法では、指定されたlayout属性はView Stubクラスの
mLayoutResource変数は、inflate Idに割り当てられます。
mInflated変数。コードは以下の通りです
        mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);
        mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
        コードでView Stub.inflate()を呼び出すと、View Stub参照のレイアウトが表示されます。
分析
View Stub.inflate()
    public View inflate() {
        final ViewParent viewParent = getParent();//    ViewStub    
        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);// inflateId                 id。   
                }

                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 {//      layout  ,     。  ,    layout  ,     xml    
                throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
            }
        } else {
            throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
        }
    }
        コードの一箇所では、指定されたレイアウトリソースによって新しいViewが生成される。したがって、View Stubのlayout属性は必ず存在し、レイアウトファイルを指す必要がある。またinflate()の最後にレイアウトファイルで生成されたビューを返します。
        コード3、4:最初にViewStubの親のレイアウトの下付きを取得し、次にView Stubを親のレイアウトから削除し、レイアウトファイルから生成されたビューを親のレイアウトに追加します。つまり、レイアウトファイルで生成されたレイアウトは、View Stubの親レイアウトの位置を入れ替えます。
        コード三、四によって、View Stubはinflateによって一旦取り除かれたら、父の配置から取り除かれますので、View Stubは一回だけです。またinflateの時は一番下のelseにまっすぐ行くからです。
        コードの4つの場所では、生成されたレイアウトをView Stubの親レイアウトに追加すると、View Stub自身のLayoutParaamsが伝えられます。したがって、レイアウトファイルのルートノードのいくつかのレイアウトパラメータは<View Stub>に設定しなければなりません。先頭のプロパティはすべて<View Stub>で設定する必要があります。
        コード5では、View Stubのidを生成されたレイアウトのidに設定します。
set Visibility()
        View Stub.set Visibility(View.VISIBLE)を呼び出すと、View Stub.inflate()と同じ効果が実行されます。例は以下の通りです
		View view = findViewById(R.id.myid);//   
		// view stub replaced with inflated layout (if stub is used in layout)
		view.setVisibility(View.VISIBLE);//   
		if (view.getParent() == null) {//   
			// a stub was used so we need to find the newly inflated view that
			// replaced it
			view = findViewById(R.id.myid);//   
		} else {
			// nothing to do, the view we found the first time is what we want
		}
        コードの一つ:R.id.myidはレイアウトにView StubのためのIDです。しかし、ここでは強くView Stubに移行していません。コードの二箇所はどのViewでもある方法です。        コードの二:コードの一箇所で得られたのはView Stubであろうと、他のViewであろうと、この方法は呼び出されます。ただし、View Stubの場合、ソースコードは以下の通りです。
    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();
            }
        }
    }
        ソースコードからは、この時も実際にinflate()を呼び出していることが分かります。inflate()はView Stubのidを生成するレイアウトのidに設定します。これはまた、コードのあちこちで得られた最新の生成のレイアウトであり、View Stubではないことを保証している。
        コード3を加えたのはコードを最適化するためです。コード2がView Stubでない場合、コードはあちこちで繰り返し起動に相当し、性能に影響を与えます。View Stub.inflate()の場合は、View Stubをその親のレイアウトから削除しますので、コードが取得されるとView Stubのコードが3つしか成立しません。したがって、コード4を実行します。得られたViewはレイアウトファイルを通じて生成された新しいレイアウトであることを保証します。
欠点
        View Stubは一回だけなので、隠しコントロールを何度も表示する必要がある場合は、GONEとVISIBLEを交互に使うしかないです。