Android —— ViewStub(惰性装载控件)的应用

ViewStub是Android中一种轻量级的惰性加载控件,它占用资源极小,初始状态下无形且不可见。在运行时,通过inflate()方法或设置可见性,ViewStub会加载指定的布局并替代自身,实现延迟加载的效果。ViewStub的属性在加载后会传递给所加载的布局。在使用中要注意布局属性需添加在ViewStub上才生效,且inflate()和setVisibility()调用后的ViewStub不能再使用inflate()进行加载,但可以再次使用setVisibility(int)设置可见。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。

1优点

 ViewStub,惰性装载控件。ViewStub是一个无形的、零大小的视图,可以在程序运行的过程中,通过懒加载的模式inflate进布局资源中。当一个ViewStub的inflate()方法被调用或者被设为显示时,这个ViewStub使用设定的View才会被加载,并替换当前ViewStub的位置。因此,ViewStub存在于视图层次,直到setVisibility(int)或inflate()方法被调用,否则是不加载控件的,所以消耗的资源小。通常也叫它为“懒惰的include”。

2基础练习

不错的讲ViewStub基础的博文
这里将博文里强调的问题,再唠叨一遍咯:
使用的时候的注意事项:

. 某些布局属性要加在ViewStub而不是实际的布局上面,才会起作用,比如上面用的android:layout_margin*系列属性,如果加在TextView上面,则不会起作用,需要放在它的ViewStub上面才会起作用。而ViewStub的属性在inflate()后会都传给相应的布局。

3属性

              <ViewStub 
              android:id="@+id/stub"
               android:inflatedId="@+id/subTree"
               android:layout="@layout/mySubTree"
               android:layout_width="120dip"
               android:layout_height="40dip" />

id:可以找到此viewStub控件
inflatedId:当控件inflate之后,可以通过这个inflatedId找到其layout。
layout:inflate之后,将原viewStub移除,获得layout布局。


注:
1.View inflated = stub.inflate();//inflate返回的是view
2.加载view之后,viewstub本身就会被新加载进来的view替换掉

官方解释:When inflate() is invoked, the ViewStub is replaced by the inflated View and the inflated View is returned. This lets applications get a reference to the inflated View without executing an extra findViewById().

4 监听事件

对于ViewStub而言,它需要监听的事件就只有一个,被加载的时候触发的事件VIewStub.OnInflateListener,在这个事件中,需要实现一个onInflate()方法,例如:

 sTubText.setOnInflateListener(new ViewStub.OnInflateListener() {
            @Override
            public void onInflate(ViewStub stub, View inflated) {

            }
        });

5 onInflate()和setVisibility()的区别

当setVisibility(int)或inflate()方法被调用之后,这个ViewStub在布局中将被使用指定的View替换,所以inflate过一遍的ViewStub,如果被隐藏之后再次想要显示,将不能使用inflate()方法,但是可以再次使用setVisibility(int)方法设置为可见。
仅第一次需要inflate(),可以通过判断异常来处理:

             try {
                    //如果没有被inflate过,使用inflate膨胀
                     LinearLayout layout=(LinearLayout)viewStub.inflate();
                     RatingBar bar=(RatingBar)layout.findViewById(R.id.ratingBar1);
                    bar.setNumStars(4);
                 } catch (Exception e) {
                     //如果使用inflate膨胀报错,就说明已经被膨胀过了,使用setVisibility方法显示
                    viewStub.setVisibility(View.VISIBLE);
                 }        

或者只用setVisibility方法,缺点是不能像inflate()一样返回layout,需要findViewByID(inflatedId)来获得。
注:setVisibility会间接调用inflate。

6.代码示例:

MainActivity:

public class MainActivity extends Activity implements View.OnClickListener {
    private ViewStub sTubText;
    private ViewStub sTubImg;
    private Button btn1;
    private Button btn2;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sTubText = (ViewStub) findViewById(R.id.viewsub_text);
        sTubImg = (ViewStub) findViewById(R.id.viewsub_img);
        btn1 = (Button) findViewById(R.id.btn_1);
        btn2 = (Button) findViewById(R.id.btn_2);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        sTubText.setOnInflateListener(new ViewStub.OnInflateListener() {//只监听调用inflate时,调用visible时不能监听到。
            @Override
            public void onInflate(ViewStub stub, View inflated) {
                Toast.makeText(getApplicationContext(), "加载了view", Toast.LENGTH_SHORT).show();

            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_1:
                sTubText.setVisibility(View.VISIBLE);//间接调用了inflate()方法。使用下面屏蔽的方法也行。
//                try {
//                    View view = sTubText.inflate();
//                    textView = (TextView) view.findViewById(R.id.text);
//                    textView.setText("打开了!!!");
//                } catch (Exception e) {
//                    sTubText.setVisibility(View.VISIBLE);
//                }
                break;
            case R.id.btn_2:
                sTubText.setVisibility(View.GONE);
                break;
        }
    }
}

main布局:

<RelativeLayout 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"
    tools:context="com.example.viewsubtest.MainActivity">
    <Button
        android:id="@+id/btn_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:text="显示"/>
    <Button
        android:id="@+id/btn_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="隐藏"/>

    <ViewStub
        android:id="@+id/viewsub_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout="@layout/layout_viewsub_text"/>

</RelativeLayout>

viewStub关联的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="viewSub测试文字"
        android:textSize="20dp"
        />

</LinearLayout>

效果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值