广告
返回顶部
首页 > 资讯 > 移动开发 >Android ViewStub使用方法学习
  • 826
分享到

Android ViewStub使用方法学习

Android ViewStub使用Android ViewStub 2022-11-16 00:11:14 826人浏览 八月长安
摘要

目录前言1.ViewStub的优势2.ViewStub的使用属性 功能简单实战1.viewstub就是动态加载试图2.看一个简单的demo3.当调用第二次inflate的时候,会报错

前言

当渲染一个活动时,这个活动的布局可能会有很多visible为invisible和Gone的情况,虽然这些控件虽然现在不显示在屏幕上,但是系统在加载这个布局文件时还是会加载它的,这就影响了这个页面的加载效率,因为这些不可见的控件提前加载它们并没有什么实际的意义,反而会减缓页面的加载时间,所以为了解决这个问题可以使用ViewStub来懒加载暂时不显示的布局.

1.ViewStub的优势

简单来说, ViewStub可以做到按需加载一个布局,我们可以控制它加载的时机,而不是在Activity的onCreate方法中去加载.即懒加载

2.ViewStub的使用

    <ViewStub
        android:id="@+id/stub"
        android:inflatedId="@+id/text"
        android:layout="@layout/text_view_stub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/textView3"
        android:layout_marginTop="180dp"
        android:layout_marginLeft="100dp"/>

属性 功能

android:inflatedId="@+id/text" 为我们要加载的布局提供一个id android:layout 我们需要加载的布局 除此之外

        app:layout_constraintTop_toBottomOf="@id/textView3"
        android:layout_marginTop="180dp"
        android:layout_marginLeft="100dp"/>

这些代表我们懒加载的布局在父布局的位置,如果懒加载的布局有相同的属性,将会被覆盖

//通过id得到viewStub对象
ViewStub viewStub = findViewById(R.id.stub);
//动态加载布局
 viewStub.inflate();

简单实战

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.ConstraintLayout
    xmlns: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">
    <TextView
        android: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"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <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"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="hide"
        android:text="hide"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="show"
        android:text="show"/>
    <ViewStub
        android: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;
    @Override
    protected 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);//null
            textView  = 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的时候,会报错:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

我们看一下这是为什么?进入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是灰色的

编辑

添加图片注释,不超过 140 字(可选)

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

编辑

添加图片注释,不超过 140 字(可选)

所以当我们第二次再调用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()为什么也可以;跟进源码看看:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

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

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

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

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

编辑切换为居中

添加图片注释,不超过 140 字(可选)

以上就是Android ViewStub的使用与简单的演练;如果想要进阶自己Android技能,可以参考这份《Android核心技术笔记》里面记录有Android的核心技术与其他前沿技术。

文末

Android ViewStub的使用注意事项

inflate方法只能调用一次,再次调用会出异常 我们看下inflate方法的源码,一旦第二次调用inflate方法,我们的到viewParent将等于null,会报 throw new IllegalStateException(“ViewStub must have a non-null ViewGroup viewParent”);异常,所以总之一句话,这个懒加载只能加载一次

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");
       }
   }

以上就是Android ViewStub使用方法学习的详细内容,更多关于Android ViewStub使用的资料请关注编程网其它相关文章!

--结束END--

本文标题: Android ViewStub使用方法学习

本文链接: https://www.lsjlt.com/news/172959.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android ViewStub使用方法学习
    目录前言1.ViewStub的优势2.ViewStub的使用属性 功能简单实战1.viewstub就是动态加载试图2.看一个简单的demo3.当调用第二次inflate的时候,会报错...
    99+
    2022-11-16
    Android ViewStub使用 Android ViewStub
  • Android组件ViewStub基本使用方法详解
    ViewStub可以在运行时动态的添加布局。帮助文档给定的定义是: "A ViewStub is an invisible, zero-sized View that can ...
    99+
    2022-06-06
    方法 viewstub Android
  • Android开发中ViewStub的应用方法
      在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么通常的想法是把可能用到的View都写在上面,先把它们的可见性都设...
    99+
    2022-06-06
    方法 viewstub android开发 Android
  • Android使用ViewStub实现布局优化方法示例
    目录实践过程实现方式知识点实践过程 Hello,大家好啊,我是小空,今天带大家了解下动态加载控件ViewStub。 在平时开发中经常会遇到复杂布局,而每一个view都是会占据内存和消...
    99+
    2022-11-13
  • 简单学习Android Socket的使用方法
    这方面的知识不是孤立的,其中有关于,Socket编程,多线程的操作,以及I/O流的操作。当然,实现方法不止一种,这只是其中一种,给同是新手一点点思路。如果有什么推荐的话,欢迎指...
    99+
    2022-06-06
    方法 socket Android
  • Android学习之菜单的使用方法
    本文实例为大家分享了Android学习之菜单使用的具体代码,供大家参考,具体内容如下 Android中菜单包含上下文菜单和选项菜单两种类型。 使用统一的菜单类来管理菜单: Menu、...
    99+
    2022-11-13
  • Android学习之Span的使用方法详解
    目录Span集合段落类Span其他Span展示效果小试牛刀小结Span集合 段落类Span BulletSpan 为段落开头增加项目符号并支持大小、颜色、弧度 span.append...
    99+
    2022-11-13
  • Android布局技巧之使用ViewStub
    多亏了<include />标签,在Android里,很容易就能做到共享和重用UI组件。在Android开发中,很容易就能创建出复杂的UI结构,结果呢,用了很多的V...
    99+
    2022-06-06
    技巧 viewstub android布局 Android
  • Android Gson基本用法学习
    目录1. 导入Android Studio工程2. 简单的 Java Object 序列化/反序列化序列化反序列化3. 嵌套 Java Object 的序列化/反序列化4. Arra...
    99+
    2022-11-12
  • Android中使用ViewStub实现布局优化
    在Android开发中,View是我们必须要接触的用来展示的技术.通常情况下随着View视图的越来越复杂,整体布局的性能也会随之下降.这里介绍一个在某些场景下提升布局性能的Vi...
    99+
    2022-06-06
    布局 viewstub 优化 Android
  • 深度学习模型的Android部署方法
    使用背景: 将python中训练的深度学习模型(图像分类、目标检测、语义分割等)部署到Android中使用。 Step1:下载并集成Pytorch Android库 下载Pytorch Androi...
    99+
    2023-09-29
    android 深度学习 人工智能
  • Java学习方法
    JAVA学习路线图,特此声明;仅希望对热爱JAVA学习有所帮助如若转载或者使用本图,请注明出处,避免后期出现版权问题,谢谢!!! JAVA学习路线图此乃是java攻城狮的学习路线图,由简到繁,由易到难,一步步的学习,最后成为JAV...
    99+
    2023-06-02
  • golang学习方法
    随着互联网的发展,各种编程语言层出不穷,其中Golang(Go语言)成为了越来越多人关注的编程语言。Golang是谷歌公司在2009年开发的一种开源编程语言,它具有高效、简单、安全等特点,并且在并发编程和网络编程方面表现突出。因此,越来越多...
    99+
    2023-05-15
  • Python3学习urllib的使用方法示例
    urllib是python的一个获取url(Uniform Resource Locators,统一资源定址符)了,可以利用它来抓取远程的数据进行保存,本文整理了一些关于urllib使用中的一些关于head...
    99+
    2022-06-04
    示例 使用方法 urllib
  • python学习pymongo模块的使用方法
    前言: pymongo模块是python操作mongo数据的第三方模块,记录一下自己常用到的简单用法。 首先需要连接数据库: MongoClient():该方法第一个参数是数据库所在...
    99+
    2022-11-11
  • 学习createTrackbar的使用方法及步骤
    createTrackbar是Opencv中的API,其可在显示图像的窗口中快速创建一个滑动控件,用于手动调节阈值,具有非常直观的效果。具体定义如下: CV_EXPORTS in...
    99+
    2022-11-12
  • 学习使用Android Chronometer计时器
    本文实例为大家分享了Android Chronometer计时器基本使用方法,供大家参考,具体内容如下 在默认情况下,Chronometer组件只输出MM:SS或H:MM:SS...
    99+
    2022-06-06
    学习 Android
  • 学习sql的方法
    这篇文章给大家分享的是有关学习sql的方法的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。学习sql的方法:首先你要掌握一定的数据库基础知识;然后你需要找一些sql的练习题来做;最...
    99+
    2022-10-18
  • 学习ActionScript3的方法
    1。当理论学不进去的时候,就应该通过实例来学 2。学习实例可以提高兴趣,熟悉代码,就算没搞懂,也能混个脸熟。 3。然后再看理论时,就会容易一些。理论是一定要看的。 4。只有实例到理论,理论再到实例,实例再到理论...
    99+
    2023-01-31
    方法
  • jsp学习之scriptlet的使用方法详解
    在JSP中,scriptlet是一种在JSP页面中嵌入Java代码的方式。它被包含在标签中,可以在其中编写任意的Java代码。下面是...
    99+
    2023-08-11
    jsp
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作