Android笔记之:深入ViewStub的应用

在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。

推荐的做法是使用android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。

但ViewStub也不是万能的,下面总结下ViewStub能做的事儿和什么时候该用ViewStub,什么时候该用可见性的控制。

首先来说说ViewStub的一些特点:

1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。

2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。

基于以上的特点,那么可以考虑使用ViewStub的情况有:

1. 在程序的运行期间,某个布局在Inflate后,就不会有变化,除非重新启动。

因为ViewStub只能Inflate一次,之后会被置空,所以无法指望后面接着使用ViewStub来控制布局。所以当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用View的可见性来控制了。

2. 想要控制显示与隐藏的是一个布局文件,而非某个View。

因为设置给ViewStub的只能是某个布局文件的Id,所以无法让它来控制某个View。

所以,如果想要控制某个View(如Button或TextView)的显示与隐藏,或者想要在运行时不断的显示与隐藏某个布局或View,只能使用View的可见性来控制。

下面来看一个实例

在这个例子中,要显示二种不同的布局,一个是用TextView显示一段文字,另一个则是用ImageView显示一个图片。这二个是在onCreate()时决定是显示哪一个,这里就是应用ViewStub的最佳地点。

先来看看布局,一个是主布局,里面只定义二个ViewStub,一个用来控制TextView一个用来控制ImageView,另外就是一个是为显示文字的做的TextView布局,一个是为ImageView而做的布局:

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="vertical"

  android:layout_width="fill_parent"

  android:layout_height="fill_parent"

  android:gravity="center_horizontal">

  <ViewStub

    android:id="@+id/viewstub_demo_text"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_marginLeft="5dip"

    android:layout_marginRight="5dip"

    android:layout_marginTop="10dip"

    android:layout="@layout/viewstub_demo_text_layout"/>

  <ViewStub

    android:id="@+id/viewstub_demo_image"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_marginLeft="5dip"

    android:layout_marginRight="5dip"

    android:layout="@layout/viewstub_demo_image_layout"/>

</LinearLayout>

为TextView的布局:

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="vertical"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content">

    <TextView

        android:id="@+id/viewstub_demo_textview"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:background="#aa664411"

        android:textSize="16sp"/>

</LinearLayout>

为ImageView的布局:

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="vertical"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content">

    <ImageView

        android:id="@+id/viewstub_demo_imageview"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

</LinearLayout>

下面来看代码,决定来显示哪一个,只需要找到相应的ViewStub然后调用其infalte()就可以获得相应想要的布局:

复制代码 代码如下:

package com.effective;

import android.app.Activity;

import android.os.Bundle;

import android.view.ViewStub;

import android.widget.ImageView;

import android.widget.TextView;

public class ViewStubDemoActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.viewstub_demo_activity);

        if ((((int) (Math.random() * 100)) & 0x01) == 0) {

            // to show text

            // all you have to do is inflate the ViewStub for textview

            ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_text);

            stub.inflate();

            TextView text = (TextView) findViewById(R.id.viewstub_demo_textview);

            text.setText("The tree of liberty must be refreshed from time to time" +

                    " with the blood of patroits and tyrants! Freedom is nothing but " +

                    "a chance to be better!");

        } else {

            // to show image

            // all you have to do is inflate the ViewStub for imageview

            ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_image);

            stub.inflate();

            ImageView image = (ImageView) findViewById(R.id.viewstub_demo_imageview);

            image.setImageResource(R.drawable.happy_running_dog);

        }

    }

}

运行结果:

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

时间: 2024-10-28 11:30:07

Android笔记之:深入ViewStub的应用的相关文章

Android笔记之:深入ViewStub的应用_Android

在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局.那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性.这样的做法的优点是逻辑简单而且控制起来比较灵活.但是它的缺点就是,耗费资源.虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性.也就是说,会耗费内存等资源. 推荐的做法是

Android布局优化之ViewStub、include、merge使用与源码分析

http://blog.csdn.net/bboyfeiyu/article/details/45869393 在开发中UI布局是我们都会遇到的问题,随着UI越来越多,布局的重复性.复杂度也会随之增长.Android官方给了几个优化的方法,但是网络上的资料基本上都是对官方资料的翻译,这些资料都特别的简单,经常会出现问题而不知其所以然.这篇文章就是对这些问题的更详细的说明,也欢迎大家多留言交流. 一.include 首先用得最多的应该是include,按照官方的意思,include就是为了解决重复

Android笔记之:App应用之发布各广告平台版本的详解_Android

Android的广告平台是很多的,各市场对各平台的接受程度是不一样的,Android的开发者如果想集成广告基本要考虑下面两个问题:(1)集成什么广告,会赚钱?(2)集成什么广告,不会被市场拒绝?最终的结果往往是折中的.第一个问题是广告平台的判断问题,我没有发言权去评论,本文主要是针对第二个问题展开.解决方案就是打包应用的不同广告平台版本,本文接下来逐一展开相关话题. 1. 基础本文其实是针对<Android笔记之:App模块化及工程扩展的应用>和<Android笔记之:App自动化之使用

Android笔记整理之常见错误及解决方案汇总_Android

一.No active compatible AVD's or devices found. Relaunch this configuration after connecting a device or starting an AVD. 修改adb server的端口,设置一个系统环境变量ANDROID_ADB_SERVER_PORT,值7913(随意一个数字),再启动adb server 步骤: a)进入cmd命令模式 b)cd XXX\platform-tools c)adb start

Android笔记整理之常见错误及解决方案汇总

一.No active compatible AVD's or devices found. Relaunch this configuration after connecting a device or starting an AVD. 修改adb server的端口,设置一个系统环境变量ANDROID_ADB_SERVER_PORT,值7913(随意一个数字),再启动adb server 步骤: a)进入cmd命令模式 b)cd XXX\platform-tools c)adb start

利用HTML5开发Android笔记

资源来自于www.mhtml5.com 杨丰盛老师成都场的PPT分享 一个很简明的demo 可以作为入门基础 学习的过程中做了点笔记 整理如下 虽然内容比较简单 但是数量还是比较多的 所以分了3篇 (上)包括Android设备多分辨率的问题,Android中构建HTML5应用程序基础 (中)包括Android与JS之间的互动,Android处理JS的警告对话框等,Android中的调试 (下)包括本地储存在Android中的应用,地理位置的应用,离线应用的构建  Android设备多分辨率的问题

【转】Android布局优化之ViewStub

ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的View,与其他的控件一样,有着自己的属性及特定的方法.当ViewStub使用在布局文件中时,当 程序inflate布局文件时,ViewStub本身也会被解析,且占据内存控件,但是与其他控件相比,主要区别体现在以下几点: 1.当布局文件inflate时,ViewStub控件虽然也占据内存,但是相相比于其他

Android开发技巧之ViewStub控件惰性装载_Android

在4.5.6节介绍过一个<include>标签,该标签可以在布局文件中引用另外一个布局文件,并可以覆盖被引用布局文件根节点所有与布局相关的属性,也就是以android:layout开头的属性.通过<include>标签可以将一个非常庞大的布局文件分解成若干个较小的布局文件,而且这些小的布局文件也可以被多次引用,从而达到一个重用的目的. <include>标签固然很好用,但有一个问题,就是布局文件中的控件并不一定在程序启动时全都用到,有一些控件只在特定的情况下才会被使用到

Android使用include/merge/ViewStub优化布局

一.使用include标签将可复用的组件抽取出来(引用布局) 二.使用merge标签减少布局的嵌套层次(merge相当于framelayout) 场景1:布局根结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替.场景2:某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时,顶结点会自动被忽略. 三.使用ViewStub标签来加载一些不常用的布局 作用:ViewStub标签同include标签一样可以用来