1.viewstub就是动态加载试图;也就是在我们的app启动绘制页面的时候,他不会绘制到view树中;当在代码中执行inflate操作后,她才会被添加到试图中。其实ViewStub就是一个宽高都为0的一个View,它默认是不可见的,只有通过调用setVisibility函数或者Inflate函数才 会将其要装载的目标布局给加载出来,从而达到延迟加载的效果,这个要被加载的布局通过android:layout属性来设置。最终目的是把app加载页面的速度提高了,使用户体验更好。

2.看一个简单的demo

viewstub.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/inflatedStart"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/hello_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"android:text="DATA EMPTY!"/></android.support.constraint.ConstraintLayout>
activity_myviewstub.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="inflate"android:text="inflate" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="setData"android:text="setdata"/><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="hide"android:text="hide"/><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="show"android:text="show"/><ViewStubandroid:id="@+id/vs"android:inflatedId="@+id/inflatedStart"android:layout="@layout/viewstub"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>
MyViewStubActivity.java
package com.ysl.myandroidbase.viewstub;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewStub;
import android.widget.TextView;import com.ysl.myandroidbase.R;public class MyViewStubActivity extends AppCompatActivity {private ViewStub viewStub;private TextView textView;private View inflate;private ConstraintLayout constraintLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_myviewstub);viewStub = findViewById(R.id.vs);//textView  = (TextView) findViewById(R.id.hello_tv);空指针,因为viewstub没有inflate}public  void inflate(View view){if (inflate == null) {//inflate只会进行一次,当第二次调用的时候,就会抛异常;也可以try catch进行处理inflate = viewStub.inflate();constraintLayout = findViewById(R.id.inflatedStart);System.out.println(constraintLayout);System.out.println("viewStub-------->"+viewStub);textView  = viewStub.findViewById(R.id.hello_tv);//获取到的textview是空的;System.out.println("viewStub textView-------->"+textView);//nulltextView  = constraintLayout.findViewById(R.id.hello_tv);System.out.println("constraintLayout textView-------->"+textView);textView  = findViewById(R.id.hello_tv);System.out.println("textView-------->"+textView);}}public void setData(View view){if (constraintLayout != null) {textView = constraintLayout.findViewById(R.id.hello_tv);textView.setText("HAVE DATA !!!");}}public void hide(View view){viewStub.setVisibility(View.GONE);
//        if (constraintLayout != null){
//            constraintLayout.setVisibility(View.GONE);
//        }}public void show(View view){viewStub.setVisibility(View.VISIBLE);
//        if (constraintLayout != null){
//            constraintLayout.setVisibility(View.VISIBLE);
//        }}
}

3.当调用第二次inflate的时候,会报错:

我们看一下这是为什么?进入viewStub.inflate();的源码:

public View inflate() {final ViewParent viewParent = getParent();if (viewParent != null && viewParent instanceof ViewGroup) {if (mLayoutResource != 0) {final ViewGroup parent = (ViewGroup) viewParent;final View view = inflateViewNoAdd(parent);replaceSelfWithView(view, parent);mInflatedViewRef = new WeakReference<>(view);if (mInflateListener != null) {mInflateListener.onInflate(this, view);}return view;} else {throw new IllegalArgumentException("ViewStub must have a valid layoutResource");}} else {throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");}}

可以看到当viewParent为空或者不是viewgroup时才会报这个错误;那么第一次调用的时候,肯定是进去了;发现一个方法replaceSelfWithView(view,parent);view就是我们在布局文件中给viewstub指定的layout所引用的那个布局;parent就是getParent方法得到的,也就是acticity的填充布局LinearLayout;

进去看一下:

private void replaceSelfWithView(View view, ViewGroup parent) {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);}}

可以发现parent.removeViewInLayout(this);把this就是viewstub从父布局linearlayout中移除了;parent.addView()就是把view(也就是我们引用的布局)添加到了父布局LinearLayout中。

我们用layout inspector来查看一下:

inflate前:可以看到viewstub是灰色的

inflate后:可以看到viewstub直接被移除了,把引用布局直接放到view树里了。

所以当我们第二次再调用inflate方法时,viewstub的parent已经为空了;就会抛出此异常;

当调用textView = viewStub.findViewById(R.id.hello_tv);//获取到的textview是空的;

而使用textView = findViewById(R.id.hello_tv);就可以直接拿到控件对象了;

当实现引用布局的显示和隐藏时,测试发现使用viewstub的setVisibility()方法可以实现,这是为什么呢?;按理说使用constraintLayout.setVisibility()当然也可以;根据上面的view树结构来看,好像使用引用布局的setVisibility()方法更合理一些;

下面我们再来看看viewstub的setVisibility()为什么也可以;跟进源码看看:

源码中使用mInflatedViewRef获取到view,然后设置隐藏与显示;mInflatedViewRef是一个view的弱引用WeakReference<View>

其实在上面的inflate方法中已经为其添加了mInflatedViewRef = new WeakReference<>(view);这个view就是viewstub中的引用布局;

所以,使用viewstub可以实现相同的显示或隐藏效果;

从上图的最后一个红色框中可以发现,假设现在我没有调用inflate方法,而是直接点击了show按钮;然后引用布局也可以绘制出来;这就是我在写demo的时候,直接上去点击show按钮,竟然也可以显示的原因。

Android之ViewStub的简单使用相关推荐

  1. android 之ViewStub

    在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局.那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在 ...

  2. android布局的效率对比,Android使用ViewStub提高布局性能

    在Android开发中,View是我们必须要接触的用来展示的技术.通常情况下随着View视图的越来越复杂,整体布局的性能也会随之下降.这里介绍一个在某些场景下提升布局性能的View,它就是ViewSt ...

  3. Android中ViewStub的使用与分析

    文章目录 1.ViewStub的简单使用 1.1 简单说明 1.2 简单示例 2.结合源码分析问题 2.1 第二次调用inflate()加载会抛出空指针异常 2.2 第二次通过调用setVisibil ...

  4. Android TabLayout(选项卡布局)简单用法实例分析

    本文实例讲述了Android TabLayout(选项卡布局)简单用法.分享给大家供大家参考,具体如下: 我们在应用viewpager的时候,经常会使用TabPageIndicator来与其配合.达到 ...

  5. android 共享数据,android进程间共享简单数据

    我们知道,在android中,保存简单的数据最方便的就是使用SharedPreferences,然而,SharedPreferences虽然说也可以设置成进程间共享数据,但是并不可靠(更致命的是,不同 ...

  6. Android PC投屏简单尝试—最终章2

    源码地址:https://github.com/deepsadness/AppRemote 上一章中,我们简单实现了PC的投屏功能. 但是还是存在这一些缺陷. 屏幕的尺寸数据是写死的 不能通过PC来对 ...

  7. Android PC投屏简单尝试—最终章1

    回顾之前的几遍文章,我们分别通过RMTP协议和简单的Socket 发送Bitmap图片的Base64编码来完成投屏. 回想这系列文章的想法来源-Vysor,它通过 USB来进行连接的.又看到了 scr ...

  8. Android PC投屏简单尝试(录屏直播)2—硬解章(MediaCodec+RMTP)

    代码地址 :https://github.com/deepsadness/MediaProjectionDemo 想法来源 上一边文章的最后说使用录制的Api进行录屏直播.本来这边文章是预计在5月份完 ...

  9. Android PC投屏简单尝试- 自定义协议章(Socket+Bitmap)

    代码地址 :https://github.com/deepsadness/MediaProjectionDemo 效果预览 投屏效果预览 简单说明: 使用Android MediaProjection ...

  10. Xamarin.Android之封装个简单的网络请求类

    http://doc.okbase.net/catcher1994/archive/220195.html Catcher8 2016/4/23 0:28:50 阅读(72) 评论(0) 一.前言 回 ...

最新文章

  1. 8086加法指令ADD
  2. win10固态硬盘分区 整数_惠普HP笔记本Win10改Win7系统教程
  3. Java PriorityQueue poll()方法与示例
  4. vue 表格中有列需要异步加载_vue.js表格分页,ajax异步加载数据
  5. dosubmit 成功不成功_什么是成功,不放弃!
  6. 测试用例和缺陷报告模板
  7. 领域驱动设计实践合订版(战略+战术)
  8. java eclipse导入工程文件_如何在Eclipse软件中导入Java工程文件
  9. FOCUS projects 5 Pro(照片景深处理软件)官方正式版V5.34.03722 | 景深合成软件下载
  10. pytorch学习之如何画损失函数曲线图
  11. via动态时间html代码,高考倒计时html代码
  12. Security:osquery 介绍
  13. TCP 的三次握手(简述)
  14. OpenBmc开发8:devtool简介与使用
  15. java 实现 公式计算
  16. 交流电压和电流数据记录器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  17. Shortest Path
  18. 浏览器自动注入js脚本
  19. 一年节气查询阳历日期与节气名称
  20. 【无限互联】iOS开发视频教程 — 3.4 @property属性和点语法

热门文章

  1. ContactsProvider的使用
  2. android qq 登陆 简书,第三方登录 — QQ登录
  3. 程序设计语言诞生——程序设计语言的发展历史
  4. 学校计算机房主机系统,学校机房电脑系统恢复的方法
  5. 计算机辅助翻译 教学大纲,《计算机辅助翻译》本科课程教学大纲翻译本科
  6. Swing数独游戏(二):终盘生成之随机法
  7. phpwind升级php7,phpwind-8.7-GBK升级到phpwind-9.02-utf8步骤详解
  8. teechart mysql_TeeChart的X轴为时间,多个Y轴的显示
  9. 计算机操作系统第二章测试题及答案
  10. cocosBuilder使用总结