ViewStub懒加载

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

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));

实际执行结果如下:

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w