android中ViewStub惰性加载布局



android中ViewStub惰性加载布局

我们先来看看看这个控件类吧

一、结构

    public final class ViewStub extends View

    

    java.lang.Object

        android.view.View

              android.view.ViewStub

二、类概述

    ViewStub 是一个隐藏的,不占用内存空间的视图对象,它可以在运行时延迟加载布局资源文件。当ViewStub可见,或者调用 inflate()函数时,才会加载这个布局资源文件。 该ViewStub在加载视图时在父容器中替换它本身。因此,ViewStub会一直存在于视图中,直到调用setVisibility(int) 或者inflate()为止。ViewStub的布局参数会随着加载的视图数一同被添加到ViewStub父容器。同样,你也可以通过使用inflatedId属性来定义或重命名要加载的视图对象的Id值。例如:

    

    通过"stud"id可以找到被定义的ViewStub对象。加载布局资源文件"mySubTree "后, ViewStub对象从其父容器中移除。可以通过id"subTree"找到由布局资源"mySubTree"创建的View。这个视图对象最后被指定为宽120dip,高40dip。执行加载布局资源文件的推荐方式如下:

    

    当inflate()被调用, 这个ViewStub被加载的视图替代并且返回这个视图对象。这使得应用程序不需要额外执行findViewById()来获取加载视图的引用。
    (译者注:这个类大概意思是用ViewStub类和在XML文件里面指定的布局资源文件关联起来,让布局资源文件在需要使用的时候再加载上去。主要作用是性能优化,什么时候用什么时候加载,不用在开始启动的时候一次加载,既可以加快程序的启动速度,又可以节省内存资源。)

 

  三、嵌套类

    接口    ViewStub.OnInflateListener        一个用于接收ViewStub已经成功加载布局资源文件的通知的监听器。

 

  四、XML属性

属性名称

相关方法

描述

android:inflatedId

setInflatedId(int)

覆盖待加载视图的id值。

android:layout

setLayoutResource(int)

为待加载的资源视图提供一个标识,在ViewStub变为可见或获取焦点时使用它。(译者注:要引用的布局资源文件id

 

  五、构造函数

    ViewStub(Context context, int layoutResource)

    创建一个与指定的布局资源文件关联的ViewStub对象。

             参数

                       layoutResource   要加载的布局资源文件的id值。 


  六、公共方法

         public void draw (Canvas canvas)

         手动在指定的画布绘制这个视图(及所有其子视图)。这个视图必须在调用这个函数之前做好了整体布局。当要自己实现一个视图时,不要重载这个方法;相反,你应该重载onDraw(Canvas)方法。(译者注:主要用于自定义的视图组件的方法。

                   参数

                            canvas    这个画布传到那个已渲染的视图对象。

 

         public int getInflatedId ()

         返回加载的布局资源文件的ID,如果加载的布局资源文件的idNO_ID,那么这个加载的View将保留它原来的id值。

                   相关XML 属性

                            android:inflatedId

                   返回值

                            一个正整数来标识这个要加载的视图或者NO_ID将保持加载视图原来的id

                   参见

                            setInflatedId(int)

 

         public int getLayoutResource ()

         返回加载的布局资源文件的id值。

                   相关XML 属性

                            android:layout

                   返回值

                            加载到视图对象的布局资源文件id值。

                   参见

                            setLayoutResource(int)

                            setVisibility(int)

                            inflate()

 

         public View inflate ()

         加载getLayoutResource()方法标识的布局资源,并通过加载布局资源替换父容器中它自己。

                   返回值

                            这个已加载的布局资源文件.

 

         public void setInflatedId (int inflatedId)

         设置加载视图的ID。如果这个idNO_ID,这个加载视图保持它原来的id不变。

                   相关XML 属性

                            android:inflatedId

                   参数

                            inflatedId         一个正整数来标识这个加载视图或者NO_ID将保持加载视图原来的id

                   参见

                            getInflatedId()

 

         public void setLayoutResource (int layoutResource)

         设置待加载的布局资源文件,当ViewStub被设置为visibleinvisible或调用inflate()时使用。这个在加载布局资源文件时创建的视图用来在父容器中替换它自己。

                   相关XML 属性

                            android:layout

                   参数

                            layoutResource       一个有效的布局资源文件id值(不等于0)。

                   参见

                            getLayoutResource()

                            setVisibility(int)

                            inflate()

 

         public void setOnInflateListener (ViewStub.OnInflateListener inflateListener)

      设置成功加载布局资源文件后事件通知的监听器。

                 参数

                            inflateListener         OnInflateListener在成功加载后得到事件通知。

                 参见

                            ViewStub.OnInflateListener

 

         public void setVisibility (int visibility)

当可见性设置为VISIBLEINVISIBLEinflate()将被调用,并且加载视图资源在父容器中替换ViewStub

                   参数

                            visibility 设置为VISIBLE(显示), INVISIBLE(隐藏) GONE(完全隐藏,不暂用布局位置).

                   参见

                              inflate() 

 

  七、受保护方法

         protected void dispatchDraw (Canvas canvas)

调用这个函数去绘制这个控件的子视图。可以通过派生类重写在绘制子类之前获取控制(但是是在他自己的视图已经被绘制完之后)

                  参数

                            canvas    这个画布传到那个已渲染的视图对象。

 

         protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)

测量这个视图以确定其内容的高度和宽度。通过measure(int, int)来调用这个方法,并且应该由子类重写以提高内容测量的效率和精确度。

    约定:当该方法被重写时,你必须调用setMeasuredDimension(int, int)来存储已测量视图的高度和宽度。否则将通过measure(int, int)抛出一个IllegalStateException异常。调用父类的onMeasure(int, int)方法是一个有效的办法。

    父类的实现是以背景大小为默认大小,除非MeasureSpec(测量细则)允许更大的背景。为了更好测量内容子类应该重写onMeasure(int, int)

    如果这个方法被重写,子类有责任确保测量它的高度和宽度至少是视图的最小宽度和高度(getSuggestedMinimumHeight()getSuggestedMinimumWidth())。

      参数

  widthMeasureSpec         由于父类有横向空间要求,参见View.MeasureSpec

                              heightMeasureSpec        由于父类有纵向空间要求,参见View.MeasureSpec 

然后,为了便于理解,小白特简单的测试了一下,直接上代码-------此处顺便测试一下include(也可以反复引用布局文件)

1、先定义一个布局文件,作为引用的布局文件---文件名为 next_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >


    <RatingBar
        android:id="@+id/rb"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />


</LinearLayout>

2、然后绘制主布局,即activity中声明加载的,即setcontentView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >


    <!-- 使用include引用布局文件 -->


    <include
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        layout="@layout/next_layout" />


    <!-- 使用ViewStub引用布局文件 -->


    <ViewStub
        android:id="@+id/stub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout="@layout/next_layout" />


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >


        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#00ffff"
            android:text="动态加载布局" />


        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:background="#ffff00"
            android:text="动态隐藏布局" />
    </LinearLayout>


</LinearLayout>

  3、在activity中测试,源码为

package com.example.viewstub;


import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RatingBar;


public class MainActivity extends Activity {
private Button button1, button2;
private ViewStub stub;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化控件
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
stub = (ViewStub) findViewById(R.id.stub);
// 为button1设置监听事件
button1.setOnClickListener(new OnClickListener() {


@Override
public void onClick(View v) {
// TODO Auto-generated method stub


// ViesStub控件只能获得一次,第二次再使用findViewById获得该ViewStub对象,则返回null

View v1 = stub.inflate();// 调用此方法,加载布局。当然也可以通过setVisibility方法
RatingBar rb = (RatingBar) v1.findViewById(R.id.rb);// 从动态加载的布局中获得相应控件
rb.setNumStars(3);// 设置已获得控件的属性


}
});
// 为button2设置监听事件
button2.setOnClickListener(new OnClickListener() {


@Override
public void onClick(View v) {
// TODO Auto-generated method stub
stub.setVisibility(View.GONE);


// 值得注意的是,若使用下面的属性值,除了占用布局空间外,而且,若是你直接点击此按钮(没有加载布局之前),则他会先自动加载布局,然后当你再次点击时,才会隐藏的。
// 这一点应该引起注意。所以 选用 View.GONE 效果更好,推荐使用。

// stub.setVisibility(View.INVISIBLE);


}
});


}


}


效果图:
进入应用的效果1


点击动态加载布局后的效果




点击隐藏布局  后效果


再一次点击动态加载布局时效果





最后,欢迎交流,本人小白    QQ 964079433
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章