ViewStub
来源:互联网 发布:腾讯企业邮箱pop 端口 编辑:程序博客网 时间:2024/04/27 20:31
参考
http://blog.csdn.net/hitlion2008/article/details/6737537。
概述
ViewStub是一种不可视,并且大小为0的视图,可以延迟到运行时填充(inflate)布局资源。当ViewStub被设置为可视或者inflate()被调用后,就会填充布局资源,然后ViewStub便会被填充的视图替代。
ViewStub是实现视图延迟加载的优秀类。无论在什么情况下,只要开发者需要根据上下文选择隐藏或者显示一个视图,都可以用ViewStub实现。或许并不会因为一个视图的延迟加载而感觉到性能 明显提升,但是如果视图树的层次很深,便会感觉到性能上的差距了。
以上两段摘自《Android开发必知的50个诀窍》
注意
一个ViewStub只能inflate()一次
在布局文件中使用ViewStub时,必须指定layout属性的值。
ViewStub被inflate()后,它所指向的布局会替换掉它在父布局中的位置。
它所指向的布局的根元素的一些布局参数,必须在<ViewStub>中进行设置,如:layout_width,layout_height等。
为<ViewStub>设置的id会被设置为布局文件生成的布局的根元素的id。
使用
在布局中使用ViewStub非常简单,跟使用TextView一样。但必须指定layout属性,且该属性必须指向一个布局文件。
可以指定inflateId属性,该属性是用来更新布局文件的根元素的id。(Overrides the id of the inflated View with this value)。
在ViewStub中构造方法中可以发现:指定的layout属性会赋值给ViewStub类中的mLayoutResource变量,inflateId会被赋值给mInflatedId变量。代码如下:
mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID); mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
在代码中调用ViewStub.inflate()就可以显示ViewStub引用的布局。
分析
ViewStub.inflate()
public View inflate() { final ViewParent viewParent = getParent();//首先得到ViewStub的父布局 if (viewParent != null && viewParent instanceof ViewGroup) { if (mLayoutResource != 0) { final ViewGroup parent = (ViewGroup) viewParent; final LayoutInflater factory; if (mInflater != null) { factory = mInflater; } else { factory = LayoutInflater.from(mContext); } final View view = factory.inflate(mLayoutResource, parent, false);//代码一 if (mInflatedId != NO_ID) { view.setId(mInflatedId);//将inflateId属性的值设置成布局文件中的根元素的id。代码五 } 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 {//如果没有指定layout属性,这里并报错。因此,必须指定layout属性,无论是通过xml还是代码 throw new IllegalArgumentException("ViewStub must have a valid layoutResource"); } } else { throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent"); } }在代码一处:通过指定的布局资源生成新的View。因此,ViewStub的layout属性必须存在,且必须指向一个布局文件。而且在inflate()的最后会把通过布局文件生成的视图返回。
在代码三、四处:首先获得ViewStub在父布局中的下标,其次将ViewStub从父布局中移除,然后将布局文件生成的视图添加到父布局中。也就是:用布局文件生成的布局会替换掉ViewStub在父布局中的位置。
通过代码三、四还可以看出:ViewStub一旦被inflate后,就会从父布局中移除掉,因而一个ViewStub只能inflate一次。因为再次inflate时会直接走到最下面的else中。
在代码四处,将生成的布局添加到ViewStub的父布局时传递了ViewStub自身的LayoutParams。因此布局文件中的根结点的有些布局参数必须在<ViewStub>中设置(如layout_width,layout_height等),但并不是所有的以layout_开头的属性都需要在<ViewStub>中设置。
在代码五处,将ViewStub的id设置为生成的布局的id。
setVisibility()
调用ViewStub.setVisibility(View.VISIBLE)时,它所执行的效果和ViewStub.inflate()一样。示例如下:
View view = findViewById(R.id.myid);//代码一// view stub replaced with inflated layout (if stub is used in layout)view.setVisibility(View.VISIBLE);//代码二if (view.getParent() == null) {//代码三// a stub was used so we need to find the newly inflated view that// replaced itview = findViewById(R.id.myid);//代码四} else {// nothing to do, the view we found the first time is what we want}代码一:R.id.myid是在布局中为ViewStub设置的id。但是这里并没有强转成ViewStub,这是因为代码二处的是任何View都有的方法。
代码二:无论代码一处得到的是ViewStub还是别的View,该方法都可以被调用。但是,如果是ViewStub,源代码如下:
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(); } } }从源代码中可以看出:此时实际上也是调用了inflate()。而inflate()中会将ViewStub的id设置为生成的布局的id。这也保证了在代码四处得到的是最新的生成的布局,而不是ViewStub。
之所以加上代码三是为了优化代码。如果代码二得到的不是ViewStub,那么代码四处就相当于重复调用,从而影响了性能。在ViewStub.inflate()时,会将ViewStub从它的父布局中移除,因此如果代码一得到的是ViewStub那么代码三才成立,从而执行代码四,保证了得到的View是通过布局文件生成的新布局。
缺点
由于ViewStub只能inflate一次,因此,对于那些需要多次显示隐藏的控件,只能交替使用GONE与VISIBLE。
0 0
- ViewStub
- ViewStub
- ViewStub
- ViewStub
- viewstub
- ViewStub
- ViewStub
- ViewStub?
- ViewStub
- ViewStub
- android ViewStub
- Android ViewStub
- ViewStub用法
- Android viewStub
- android viewstub
- android ViewStub
- ViewStub初探
- android ViewStub
- linux之device_init()
- 20条Linux命令面试问答
- GDKOI2015D2T1
- Xcode 7测试化工具XCTestCase
- tabbarcontroller+navigationcontroller 导航栏错乱的问题
- ViewStub
- Win7不重启系统 使修改后的环境变量生效
- 集训队专题(1)1002 统计难题
- 原始版本的murmurhash2算法
- android override
- iOS开发-进阶:音频播放、录音、视频播放、拍照、视频录制
- Intent
- mysql 各种实际常用疑难sql整理
- Linux下安装Maven