ViewStub --- 视图的使用

在使用之前首先要知道什么是ViewStub?

ViewStub其实本质上也是一个View,其继承关系如图所示:
ViewStub

为什么ViewStub可以提高加载性能?

ViewStub使用的是惰性加载的方式,即使将其放置于布局文件中,如果没有进行加载那就为空,不像其它控件一样只要布局文件中声明就会存在。
那ViewStub适用于场景呢?通常用于网络请求页面失败的显示。一般情况下若要实现一个网络请求失败的页面,我们是不是使用两个View呢,一个隐藏,一个显示。试想一下,如果网络状况良好,并不需要加载失败页面,但是此页面确确实实已经加载完了,无非只是隐藏看不见而已。如果使用ViewStub,在需要的时候才进行加载,不就达到节约内存提高性能的目的了吗?

ViewStub的加载原理

ViewStub只能加载一次,重复加载会导致异常,这是因为ViewStub只要加载过一次,其自身就会被移除,把并自身所包含的内容全部传给父布局。
这里写图片描述

ViewStub如何使用

父布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.administrator.myviewstub.MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="inflate"
        android:text="inflate" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="setData"
        android:text="setdata"/>
    <ViewStub
        android:id="@+id/vs"
        android:layout="@layout/viewstub"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

可以看到ViewStub又引用了另外一个布局。

ViewStub布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:id="@+id/hello_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="DATA EMPTY!"/>
</FrameLayout>

MainActivity

public class MainActivity extends AppCompatActivity {
    private ViewStub viewStub;
    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewStub = (ViewStub) findViewById(R.id.vs);
        //textView  = (TextView) findViewById(R.id.hello_tv);空指针
    }
    public  void inflate(View view){
        viewStub.inflate();
        //textView  = (TextView) viewStub.findViewById(R.id.hello_tv);空指针
        textView  = (TextView) findViewById(R.id.hello_tv);
    }
    public void setData(View view){
        textView.setText("DATA!!");

    }
}
注意:

这里有几个坑,前面我们说了ViewStub只有在初始化之后才会存在,所以第一个注释中的空指针是因为ViewStub还未初始化。那第二个注释中的空指针是怎么回事呢?前面我们也说了,ViewStub在加载完成之后会移除自身,并把自身的内容转给父布局,所以此时viewStub中的内容已经不存在了,textView已经是父布局的东西了,所以不能使用viewStub来findViewById。另外,前面我们说了ViewStub只能加载一次,若调用两次inflate()的话会导致异常。

翻看源码只有就可以看到,ViewStub若之前没有进行inflate,setVisibility(View.VISIBLE)或setVisibility(View.INVISIBLE)会自动先进行加载,而加载之后可以设置显示和隐藏。并且ViewStub设置的不是自己,而是拿到关联的那个Layout设置visible。ViewStub此时并未销毁,所以建议初始化后将其设置为空。

自己写了一个栗子:

ViewStub 是一种可以动态加载的布局,默认情况下不显示

1 、定义要引入的布局,如: title_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/title_height"
    android:background="@color/title_color">
    <TextView
        android:id="@+id/title_left_view"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/title_height"
        android:layout_marginLeft="3dp"
        android:gravity="center_vertical"
        android:textColor="#ffffffff"
        android:textSize="18sp"/>
    <TextView
        android:id="@+id/title_center_view"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/title_height"
        android:gravity="center_vertical"
        android:textColor="#ffffffff"
        android:layout_centerInParent="true"
        android:text=" 登录 "
        android:textSize="24sp" />
    <TextView
        android:id="@+id/title_right_view"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/title_height"
        android:gravity="center_vertical"
        android:textColor="#ffffffff"
        android:layout_alignParentRight="true"
        android:textSize="18sp"
        android:layout_marginRight="3dp"/>

</RelativeLayout>

2 、定义 ViewStub 引入布局

<ViewStub
    android:id="@+id/title_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout="@layout/title_layout"/>

3 、 java 中动态控制

// 显示标题
ViewStub titleView = (ViewStub) findViewById(R.id.title_view);
titleView.setVisibility(View.VISIBLE);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值