ViewStub懒加载

QuibblerQuibbler 2019-10-25 约 8 分钟 2208 次阅读

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(),在调用ViewStub的inflate()方法初始化ViewStub对象:

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

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

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

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

@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,如果返回值不为null则ViewStub没有被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();
    }

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


4、注意*

ViewStub所包含布局中的控件在ViewStub被inflate()之前都不可用,也不能被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引入布局中的控件。但是仍然不能通过ViewStub去findViewById(),因为被加载的布局是替换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));

实际执行结果如下:

相关推荐

WilliamChart:轻量美观的 Android 图表库实战
精选开源

WilliamChart:轻量美观的 Android 图表库实战

WilliamChart:轻量美观的 Android 图表库实战数据可视化是运动、健康、金融、统计类 App 的刚需。MPAndroidChart 功能最全但偏重复杂,WilliamChart 走的则是"轻量 + 美观 + Kotlin 原生"路线——v3 用 Kotlin 完全重写,API 极简,一行 chart.animate(dataSet) 就能把数据画成带动画的折线/柱状/环形图,开箱即

175