热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android之ViewStub的简单使用

1.viewstub就是动态加载试图;也就是在我们的app启动绘制页面的时候,他不会绘制到view树中;当在代码中执行inflate操作后

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

2.看一个简单的demo

viewstub.xml


activity_myviewstub.xml


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 &#61; getParent();if (viewParent !&#61; null && viewParent instanceof ViewGroup) {if (mLayoutResource !&#61; 0) {final ViewGroup parent &#61; (ViewGroup) viewParent;final View view &#61; inflateViewNoAdd(parent);replaceSelfWithView(view, parent);mInflatedViewRef &#61; new WeakReference<>(view);if (mInflateListener !&#61; 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时才会报这个错误&#xff1b;那么第一次调用的时候&#xff0c;肯定是进去了&#xff1b;发现一个方法replaceSelfWithView(view,parent)&#xff1b;view就是我们在布局文件中给viewstub指定的layout所引用的那个布局&#xff1b;parent就是getParent方法得到的&#xff0c;也就是acticity的填充布局LinearLayout&#xff1b;

进去看一下&#xff1a;

private void replaceSelfWithView(View view, ViewGroup parent) {final int index &#61; parent.indexOfChild(this);parent.removeViewInLayout(this);final ViewGroup.LayoutParams layoutParams &#61; getLayoutParams();if (layoutParams !&#61; null) {parent.addView(view, index, layoutParams);} else {parent.addView(view, index);}}

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

我们用layout inspector来查看一下&#xff1a;

inflate前&#xff1a;可以看到viewstub是灰色的

inflate后&#xff1a;可以看到viewstub直接被移除了&#xff0c;把引用布局直接放到view树里了。

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

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

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

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

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

源码中使用mInflatedViewRef获取到view&#xff0c;然后设置隐藏与显示&#xff1b;mInflatedViewRef是一个view的弱引用WeakReference

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

所以&#xff0c;使用viewstub可以实现相同的显示或隐藏效果&#xff1b;

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

 

 


推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 今天就跟大家聊聊有关怎么在Android应用中实现一个换肤功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根 ... [详细]
  • SmartRefreshLayout自定义头部刷新和底部加载
    1.添加依赖implementation‘com.scwang.smartrefresh:SmartRefreshLayout:1.0.3’implementation‘com.s ... [详细]
  • 在一对一直播源码使用过程中,有时会出现软键盘切换闪屏问题,就是当切换表情的时候屏幕会跳动,因此要对一对一直播源码表情面板无缝切换进行优化。 ... [详细]
  • 2021年最详细的Android屏幕适配方案汇总
    1Android屏幕适配的度量单位和相关概念建议在阅读本文章之前,可以先阅读快乐李同学写的文章《Android屏幕适配的度量单位和相关概念》,这篇文章 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 本文介绍了一款名为TimeSelector的Android日期时间选择器,采用了Material Design风格,可以在Android Studio中通过gradle添加依赖来使用,也可以在Eclipse中下载源码使用。文章详细介绍了TimeSelector的构造方法和参数说明,以及如何使用回调函数来处理选取时间后的操作。同时还提供了示例代码和可选的起始时间和结束时间设置。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 正则表达式及其范例
    为什么80%的码农都做不了架构师?一、前言部分控制台输入的字符串,编译成java字符串之后才送进内存,比如控制台打\, ... [详细]
  • Editedbymythouhttp:www.cnblogs.commythoupublicbooleancreateReflectedForAdapter(){finalintr ... [详细]
author-avatar
zhaoyunnidaye_260
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有