ViewStub(笔记)

今天在对项目做优化的时候,了解到了一个控件叫ViewStub。

主要的背景是在一般情况下,在一个布局里,我们对于里面的某部分的布局需要进行隐藏的操作,那么我们会采用View.INVISIBLE或是View.GONE。但它有个缺点就是太过于耗费内存了,虽然表面上你是看不到,但其实当你进入界面的时候,就已经按照常规同样进行绘制。而ViewStub则是由于设计的原因,是耗费内存很低,等到有需要的时候才会去将我们要的布局给显示出来了。


首先看一下代码:

MainActivity.class

public class MainActivity extends Activity {
	private Button bt_showButton , bt_hideButton ;
	private ViewStub viewStub;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        bt_showButton = (Button) findViewById(R.id.bt_show);
        bt_hideButton = (Button) findViewById(R.id.bt_hide);
     
        viewStub = (ViewStub) findViewById(R.id.viewstub);
        
        bt_showButton.setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
//				try {
//					viewStub.inflate();
//				} catch (Exception e) {
//					// TODO: handle exception
//					viewStub.setVisibility(View.VISIBLE);
//				}
				if(viewStub.getParent() != null){
					viewStub.inflate();
					Log.d("MainActivity", "inflate");
				}else {
					viewStub.setVisibility(View.VISIBLE);
					Log.d("MainActivity", "visibility");
				}
				
			}
		});
        
        bt_hideButton.setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				viewStub.setVisibility(View.GONE);
			}
		});       
    } 
}


activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.viewstubtest.MainActivity" >

    <Button 
        android:id="@+id/bt_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="显示"/>
    <Button 
        android:id="@+id/bt_hide"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="隐藏"/>
    
    <ViewStub 
        android:id="@+id/viewstub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/other"/>
  
</LinearLayout>

other.xml是你想要隐藏的布局,这里就不写了。

在布局文件里,我们利用layout将要隐藏的布局跟ViewStub关联起来,然后在代码里,当需要显示的时候,就通过inflate()方法将它显示出来,不过要注意这里的inflate只能在第一次要显示的时候调用,当我们进行隐藏(GONE)重新显示的时候,则应该是用VISIBLE来显示,如果你再次调用inflate,它就会报错(ViewStub must have a non-null ViewGroup viewParent)。这些主要是我们要通过源码去分析,当然还有官方文档。


接下来通过工具来分析看下:

当一开始还没有进行操作的时候,根据布局的分析是只有四个控件


当我们点击显示的时候,我们发现布局的空间发生了改变,我们要隐藏的布局都显示出来了


接下来当我们点击隐藏的时候,我们发现就与以前的一样,隐藏的布局不会变回ViewStub,而是还在,只是隐藏了而已。



所以当我们第一次进入某个界面的时候,我们通过ViewStub可以节省很大的内存,原因在于根据源码我们可以看到

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(0, 0);
    }

在测量都时候就给自己0的设定,所以它是没有尺寸的。


一些小点:

1.ViewStub只能用于绑定一个布局,而不能绑定一个单独的View控件

2.不支持<merge />标签。(这个也是在看布局优化的文章时说到,说有时候我们会用Include来进行一个公共的套用,这样也是优化的一种方法,但它如果根布局与现有的布局其实一样,也就会产生一个重复的布局,如果我们把根布局换成<merge />标签,则它就会自动的嵌套入当前需要的位置的根布局里,就避免了多一个重复的布局。)

3.现在我们看到的textview其实是已经在布局文件里把内容写好了的,我刚才在想如果要是放到有网络请求里的怎么办,它的内容是会变的。就看到了可以这样解决的方法:

if (viewStub.getParent() != null) {
					View view = viewStub.inflate();

					tv1 = (TextView) view.findViewById(R.id.tv1);
					
					tv1.setText("ok");
					
					Log.d("MainActivity", "inflate");
				} else {
					viewStub.setVisibility(View.VISIBLE);
					Log.d("MainActivity", "visibility");
				}
所以我觉得是数据请求后保存下来,一旦ViewStub被要求显示了,就将其内容填充。


参考和扩展:

Android实战技巧:ViewStub的应用

ViewStub(官方,应该需要科学上网)

Android学习笔记31:使用惰性控件ViewStub实现布局动态加载


ViewStub用法分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值