ViewStub懒加载 View

Quibbler 2019-10-25 716

ViewStub懒加载


         ViewStub常用于优化布局,使用它可以提高布局加载的性能。


1、ViewStub介绍

        ViewStub继承自View

        ViewStub默认是不可见(GONE),而且View的大小为0

        当一个ViewStub被设置成可见visible或者调用inflate()方法时,ViewStub得到填充。此时ViewStub所引用的layout布局会替换掉当前ViewStub显示出来。



2、使用ViewStub

        和使用其它控件一样,在布局中用<ViewStub />标签来使用ViewStub

    <ViewStub
        android:id="@+id/view_stub"
        android:inflatedId="@+id/inflate_layout"
        android:layout="@layout/more_text" />

        三个属性提一下:id就是当前ViewStub的id;inflatedId是布局被加载出来的要设置id;layout是需要加载的布局。



3、ViewStub加载布局

        

3.1、通过inflate()方式加载布局

        先通过findViewById(),在调用ViewStubinflate()方法初始化ViewStub对象:

    ViewStub mViewStub= (ViewStub) findViewById(R.id.view_stub);
    View inflated = mViewStub.inflate();

        ViewStub在第一次加载完成之后会移除自身,并把自身的内容转给父布局;所以不能借助ViewStubfindViewById()查找包所含布局中的控件。另外,ViewStub只能加载一次,若多次调用inflate()会导致异常:"ViewStub must have a non-null ViewGroup viewParent"


3.2、通过设置setVisibility()加载布局

        直接通过设置ViewStub的setVisibility()ViewStub第一次被设置成VISIBLE的时候会自动调用inflate()加载布局,即使后面多次设置VISIBLE也不会出错。比直接调用ViewStubinflate()方法相对安全一些。

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.show_view_stub:
                mViewStub.setVisibility(View.VISIBLE);
                break;
            case R.id.hide_view_stub:
                mViewStub.setVisibility(View.GONE);
                break;
            default:
                break;
        }
    }


3.3、判断ViewStub是否已经加载布局

        ViewStub调用inflate()后会被从布局中移除。所以每次在inflate的时候重新findViewById()去页面中寻找一下ViewStub,如果返回值不为nullViewStub没有被inflate。

    // 每次在inflate之前都调用一遍findViewById
    ViewStub viewStub=  (ViewStub) findViewById(R.id.viewstub);
    if(viewStub!=null){
        viewStub.inflate();
    }

        利用ViewStub的parent来判断。当ViewStub被inflate后,会被从布局中移除,其getParent()返回值是null

    //初始化,不必每次都调用ViewStub viewStub=  (ViewStub) findViewById(R.id.viewstub);
    ....
    if(viewStub.getParent() !=null){
        viewStub.inflate();
    }

        通过打印日志,查看ViewStubgetParent()是否为空,当ViewStub没被加载可以getParent()获取到父布局。但一旦调用过ViewStubinflate()方法,那么getParent()就会返回null;可以通过这个方式来判断ViewStub是否已被加载。如下:初始化-> inflate() -> 隐藏。可以看见inflate()之后getParent()为null。




4、注意*

        ViewStub所包含布局中的控件在ViewStubinflate()之前都不可用,也不能被findViewById()查找到,因为还没有添加到当前布局中:

        mViewStub = findViewById(R.id.test_view_stub);
        mImageView = findViewById(R.id.view_stub_image);
        Log.e(TAG, "初始化ViewStub中的ImageView:\tImageView == null:" + (mImageView == null));
        mImageView = mViewStub.findViewById(R.id.view_stub_image);
        Log.e(TAG, "初始化ViewStub中的ImageView:\tImageView == null:" + (mImageView == null));

      结果都不能初始化ViewStub中的ImageView,均为空:

        直到ViewStub被加载之后,ViewStub被布局中的内容替换,可用直接通过findViewById()找到由ViewStub引入布局中的控件。但是仍然不能通过ViewStubfindViewById(),因为被加载的布局是替换ViewStub,被添加到ViewStub所在的父布局,而不是添加到ViewStub中。通过ViewStub获得的控件仍然是null。

mViewStub.inflate();
Log.e(TAG, "初始化ViewStub中的ImageView: findViewById()\tImageView == null:" + (findViewById(R.id.view_stub_image) == null));
Log.e(TAG, "初始化ViewStub中的ImageView: ViewStub.findViewById()\tImageView == null:" + (mViewStub.findViewById(R.id.view_stub_image) == null));

      实际执行结果如下:



不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com