AndroidではView Stubを使ってレイアウトの最適化を実現します。

8944 ワード

Androidの開発では、Viewは私たちが触れなければならない技術です。通常はViewビューが複雑になるにつれて、全体のレイアウトの性能も低下します。ここでは、いくつかのシーンでレイアウト性能を向上させるViewを紹介します。それはView Stubです。
View Stubは何ですか
  • View StubはViewのサブ
  • である。
  • は見えません。サイズは0
  • です。
  • は、レイアウトリソースのロードを遅延させるために使用される。
  • 注、Stubについての説明
    A stub is a small program routine that substitutes for a longer program、possibly to be loaded later or that is located remotely
    Javaでは、杭とは、関連コードまたは未実現コードの代わりに使用されるコードのことです。
    View Stub使用シーン
     
    上の図のように、
  • のListViewは、ニュース、ビジネス、科学技術などのItem
  • を含んでいます。
  • 各Itemにはそれぞれのサブテーマが含まれています。
  • しかし、子供の話題のView(青い領域)は、展開ボタンをクリックしてこそロードが必要です。
  • サブトピックのViewをデフォルトでロードすると、メモリの占有とCPUの消費が発生します。
  • だから、この時はView Stubを使います。View Stubを使うとレイアウトリソースのロードが遅くなります。
    View Stubはどう使いますか
    レイアウトファイルにView Stubタグを使う
    
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin"
      android:paddingBottom="@dimen/activity_vertical_margin"
      tools:context="com.droidyue.viewstubsample.MainActivity">
    
     <Button
       android:id="@+id/clickMe"
       android:text="Hello World!"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
     
     <ViewStub
       android:id="@+id/myViewStub"
       android:inflatedId="@+id/myInflatedViewId"
       android:layout="@layout/include_merge"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@id/clickMe"
     />
    </RelativeLayout>
    
    
    2.コードの中でinflateレイアウト
    
    ViewStub myViewStub = (ViewStub)findViewById(R.id.myViewStub);
    if (myViewStub != null) {
     myViewStub.inflate();
     //          
     //myViewStub.setVisibility(View.VISIBLE);
    }
    
    View Stubについて
    inflateメソッドの他に、set Visibility()メソッドを呼び出してレイアウトファイルをロードすることもできます。
    ロードレイアウトが完了すると、View Stubは現在のレイアウト階層から削除されます。
    android:idはView Stub IDを指定し、View Stubを検索して遅延負荷を行う。
    Android:layout遅延負荷レイアウトのリソースID
    Android:inflatdedで読み込まれたレイアウトが書き換えられたidで、ここはRelativelayoutのidです。
    View Stubの不足
    公式文書にはこんな記述があります。
    Note:One drawback of View Stub is that it doesn't currently support the(in the layouts to be inflated)
    View Stubがサポートしていないという意味です。
    ラベルがサポートされていない程度について、簡単に検証します。
    検証一:直接ラベル
    下のようにレイアウトファイルの名前があります。layout.xml
    
    <merge xmlns:android="http://schemas.android.com/apk/res/android">
    
     <Button
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="Yes"/>
    
     <Button
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="No"/>
    
    </merge>
    
    
    対応するView Stubのandroid:layout属性値を置換した後、運転後(Buttonボタンをクリックして)次のような崩壊が発生しました。
     E Android_Runtime:android.view.Inflate Exception:Binary XML file line:can be used only with a valid View root and atach Toroot=true
     E Android Runtime:         at android.view.Layout Inflater.inflate(Layout Inflater.java:551)
     E Android Runtime:         at android.view.Layout Inflater.inflate(Layout Inflater.java:429)
     E Android Runtime:         at android.view.View Stub.inflate(View Stub.java:259)
     E Android Runtime:         at comp.droid dyue.view stubsample.MainActivity$1.onClik(MainActivity.java:20)
     E Android Runtime:         at android.view.View.performClick(View.java:5697)
     E Android Runtime:         at android.widget.TextView.performClick(TextView.java:1085)
     E Android Runtime:         at android.view.View$PerformClick.run(View.java:22526)
     E Android Runtime:         at android.os.Handler.handlee Callback(Handler.java:739)
     E Android Runtime:         at android.os.Handler.dispatch Message(Handler.java:95)
     E Android Runtime:         at android.os.Looper.loop(Looper.java:158)
     E Android Runtime:         at android.ap.ActivityThread.main(ActivityThread.java:7237)
     E Android Runtime:         at java.lang.reflect.Method.invoke(Native Method)
     E Android Runtime:         at comp.android.internal.os.ZygoteInit$MethodAndArgs Caller.run(ZygoteInit.java:1230)
     E Android Runtime:         at comp.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
     E Android Runtime:Caused by:android.view.Inflate Exception:can be used only with a valid View Groot and atach ToRoot=true
     E Android Runtime:         at android.view.Layout Inflater.inflate(Layout Inflater.java:491)
     E Android Runtime:         ... 13メモリ
    表示されている直接的なタグは、View Stubはサポートされていません。
    二間接的なView Stubを検証します。
    下のレイアウトは間接的にmergeタグを使いました。ファイル名はinclude_です。merge.xml
    
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
      <include layout="@layout/merge_layout"/>
    </LinearLayout>
    
    そしてView Stubのandroidを修正します。layout値は運行します。正常です。
    また、この例では、View Stubも<include>タグに対して良好なサポートをしていることを検証した。
    View Stubの一点コード解析について
    inflate vs set Visibility
    inflateとset Visibilityの共通点は、ロードレイアウトを実現できることです。
    
    /**
      * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},
      * {@link #inflate()} is invoked and this StubbedView is replaced in its parent
      * by the inflated layout resource.
      *
      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
      *
      * @see #inflate() 
      */
     @Override
     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();
       }
      }
     }
    
    set VisibilityはView Stubの初回遅延初期化時のみ、visibilityが非GONEの場合はinflate方法を呼び出しました。
    inflateソース
    次のinflateを読むことによって実現します。私達はもっと理解します。
  • android:inflatedの用途
  • ViewStubは、初期化後にビュー階層から
  • を除去する。
  • View StubのlayoutParametersアプリケーション
  • mInflate View Refは弱い引用形式を通じて、ViewStubとロードされたViewとの連絡を確立する。

  • 
    /**
      * Inflates the layout resource identified by {@link #getLayoutResource()}
      * and replaces this StubbedView in its parent by the inflated layout resource.
      *
      * @return The inflated layout resource.
      *
      */
     public View inflate() {
      final ViewParent viewParent = getParent();
    
      if (viewParent != null && viewParent instanceof ViewGroup) {
       if (mLayoutResource != 0) {
        final ViewGroup parent = (ViewGroup) viewParent;
        final LayoutInflater 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");
      }
     }
    
    
    View Stubについての研究はこれらです。みなさんの最適化について役に立つと思います。