官网链接:https://developer.android.com/reference/android/view/ViewStub
翻译:ViewStub 是一个不可见的,零大小的视图,可用于在运行时延迟扩展布局资源。当 ViewStub 可见时,或者调用 inflate() 时,布局资源会 inflate 。然后, ViewStub 会在其父级中使用 inflated 的视图替换自身。因此,直到调用 setVisibility() 或 inflate() 方法的时候, ViewStub 才会被添加到视图层次结构中。 ViewStub 所拥有的布局参数会被添加到指向布局文件的根布局里。同样,我们可以使用 ViewStub 的inflatedId 属性定义/覆盖 被添加布局文件的根布局的 id。
示例:
<ViewStub android:id="@+id/stub"
android:inflatedId="@+id/subTree"
android:layout="@layout/mySubTree"
android:layout_width="120dip"
android:layout_height="40dip" />
可以使用 id:stub 找到定义的 ViewStub 。在布局资源 myStubTree inflate之后, ViewStub 将从其父级中删除。我们可以通过属性 inflatedId 属性指定的 id:subTree 来找到布局资源。最终为 inflate 的视图指定的宽度为120dp,高度为40dp。
使用方法:
ViewStub stub = findViewById(R.id.stub);
View inflated = stub.inflate();
当调用 inflate() 方法时,ViewStub 会被布局文件里面的布局替换掉。所以只需要执行这一次 findViewById() 就可以了。
这是官方的讲解,下一篇讲一下我们如何在项目里使用和一些常见的错误。
在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或者某个布局。那么最通常的想法就是把可能用到的view下载布局里面,利用view的可见性,在代码中动态的更改它的可见性。
这种做法的有点:逻辑简单,控制起来比较灵活。
缺点:耗费资源。为什么了?虽然view的初始化可见view。GONG ,但是在inflate布局的时候view仍然会被绘制,也就是说会创建对象,会被实例化,会这是属性。==耗费内存资源。
推荐做法:使用android.view.ViewStub,ViewStub是一个轻量级的view,ViewStub是一个轻量级的view,他是一个看不见,不占布局位置,占用资源非常小的控件。
可以为ViewStub指定一个布局文件,在inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被inflate和实例化,然后ViewStub的布局属性都会传给他所指向的布局。这样就可以使用ViewStub在运行的时候,来确定显不显示某个布局。
ViewStub 的一些特点
1)ViewStub 只能inflate一次,之后ViewStub对象会被置为null。换句话说,某个ViewStub指定的布局被inflate后,就不会通过ViewStub来控制它了。
2)ViewStub 只能用来inflate一个布局文件,而不是某个具体的view,当然也可以吧view卸载某个布局文件中。
基于以上特点,可以考虑使用ViewStub的情况有:
1)当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用view的可见性来控制了。
2)想要控制显示与隐藏的是一个布局文件,而非某个view。
注意事项
某些属性要加在ViewStub才有用,比如android:layout_margin*系列属性。
参考文章:
ViewStub基本用法
ViewStub源码分析
Android提高布局加载性能ViewStub的快速实战应用