Hack 2-延迟加载(Lazy Loading)与避免重复的布局代码

当你在创建一个非常复杂的布局的时候,你会发现你自己添加了一大推的ViewGroups和Views。但是你的布局的层次越深,程序的效率就会越低。所以一个优化的布局,对于创建一个运行迅速、快速反应用户的操作的程序是非常重要的。

在这次的Hack中,你将会学到如何在你的xml布局中使用<include/>标签来避免重复代码,也将会学到如何用ViewStub来延迟加载View。


2.1 使用<include/>标签来避免重复代码


让我们来想象一个很简单的场景:我们要在应用中的每一个View添加一个footer视图,比如一个现实我们应用名称的TextView。如果我们有很多Activity,那么将需要多个xml文件。我们是否可以将这个TextView拷贝到每一个布局文件当中?如果将来我们有需要来编辑它怎么办?复制粘贴是一个方法,但是却不是非常的高效。最简单的方法是用<include/>标签来给我们的布局添加footer。让我们看看它是如何帮助我们的。

我们可以用<include/>标签来将一个xml文件的布局添加到另外一个xml文件的布局当中。在我们的例子中,我们创建一个完整的View,然后添加一个<include/>来指向我们的footer布局。我们Activity其中的一个布局文件是如下这个样子的:

<RelativeLayout 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: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" >

<TextView
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_centerInParent="true"
	android:gravity="center_horizontal"
	android:text="@string/hello"
	/>
<include 
    layout="@layout/footer_with_layout_properties"
    />

</RelativeLayout>

而footer的布局文件是如下这个样子滴:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_alignParentBottom="true"
	android:layout_marginBottom="30dp"
	android:gravity="center_horizontal"
	android:text="@string/footer_text"
/>

在这第一个例子当中,我们在<include/>标签中使用了我们特定的layout布局。那你可能就会问了:OK,这里有效是因为我们的主xml布局文件是一个RelativeLayout,如果我们的另一个布局文件是LinearLayout该怎么办呢?android:layout_alignParentBottom="true"这个属性就不会有效了,因为它只是RelativeLayout的属性。

上述所说明的的确是个问题,让我们看看第二种使用includes的方法,在这里,我们可以将android:layout....这样的标签放在<include/>当中。

下面这个xml文件中,我们修将android:layout_*这样的属性放到了<include/>标签中:

<RelativeLayout 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: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" >

<TextView
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_centerInParent="true"
	android:gravity="center_horizontal"
	android:text="@string/hello"
	/>
<include
	layout="@layout/footer"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_alignParentBottom="true"
	android:layout_marginBottom="30dp"
/>
</RelativeLayout>

下面是修改过的footer.xml:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="0dp"
	android:layout_height="0dp"
	android:gravity="center"
	android:text="@string/footer_text"
/>

在这第二个例子当中,我们一定要注意,如果我们要使用android:layout_*之类的属性,我们必须先指定android:layout_width与android:laytout_height这两个属性。

在这里Hack中,我们要注意一个小细节:我们把android:layout_*属性转移到了<include/>标签中。再看一下footer.xml中的width与height,你会发现它们都是0dp。我们这么做是因为我们希望码农在使用这个footer.xml时结合<include/>来指定height和width。如果码农不在<include/>中加这两个属性的话,我们将会看不到footer因为它们的height和width都是0dp。



2.2 使用ViewStub实现延迟加载视图(Views)


当我们在设计布局时,你可能会考虑到根据用户的操作来显示不同的布局。如果你以前是用让一个View变为invisible与visible来实现视图的变化的话,你就需要继续往下读了。ViewStub会成为你的更优的选择。


为了介绍一下这个ViewStub,我们先来看一下Android的官方文档:

ViewStub是一个不可见的、长度宽度为0的View,它可以在程序运行时从布局资源(layout resources)中延迟(异步?)加载。当ViewStub可见的时候,或是当inflate()函数被调用的时候,布局文件就已经被加载了。然后被加载的View或Views就会替代ViewStub。

这下你就了解了什么是ViewStub,让我们看看它可以做什么。在下面的这个例子当中,我们用ViewStub来延迟加载一个MapView。想象一下我们要展示某一个地点的具体信息,有如下的两种可能的场景:

  • 一些没有GPS信息的场景
  • 用户不需要地图

如果当前的场景中没有GPS信息,我们就不能将一个标记放置在地图上,另外如果用户不需要看地图,我们为什么要加载它们?我们将MapView放在ViewStub中,然后让用户决定是否加载这个地图。为了实现它,我们需要下面这个布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">
<Button
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:text="@string/show_map"
	android:onClick="onShowMap"/>
<ViewStub
	android:id="@+id/map_stub"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:layout="@layout/map"
	android:inflatedId="@+id/map_view"/>
</RelativeLayout>

很明显,我们需要ViewStub的Id来在Activity中获取它,它的layout属性说明了它要加载哪一个布局文件。下面是地图的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.maps.MapView
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:clickable="true"
	android:apiKey="my_api_key"/>

最后一个我们需要讨论的属性是:inflatedId。inflatedId是我们在调用inflate()或setVisibility()之后使用的View的ID。在这个例子中我们使用setVisibility(View.VISIBLE),因为我们对MapView不进行任何别的操作。如果我们想获取被加载的布局的引用,我们只需要用inflate()这个方法,它会返回一个view类型来避免二次调用findViewById()。

Activity的代码很简单,如下:

public class MainActivity extends Activity {
	private View mViewStub;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main3);
		mViewStub = findViewById(R.id.map_stub);
		
	}
	public void onShowMap(View v) {
		mViewStub.setVisibility(View.VISIBLE);
		}
}

正如你所看到的,当我们需要展示地图的时候我们只需要变化ViewStub的Visibility就可以。


2.3 总结


<include/>是一个让你的布局井然有序的工具。如果你已经用过Fragment,你就会注意到它与使用include差不多就是一个道理。正如你对Fragments做的一样,你的界面的视图可以由好多<include/>组成。

<include/>标签提供了一个非常好的整理你的布局的方法,如果你在创建一个非常复杂的布局,layout文件变得特别的大,这个时候你就可以尝试用include来分解你的布局。xml文件可读性将会更强,条理性也会更好。

ViewStub是一个极好的延迟加载布局的类,每当你想根据场景隐藏或是展示一个View的时候,你就可以尝试使用ViewStub。可能当只有一个View的时候你不会注意到启动速度的优化,但是当布局变得很深很复杂的时候,性能就会变得很好。


2.4 相关链接


http://code.google.com/p/android/issues/detail?id=2863
http://android-developers.blogspot.com.ar/2009/03/android-layout-tricks-3-optimize-with.html
http://developer.android.com/reference/android/view/ViewStub.html



转载请注明原地址,谢谢!

http://blog.csdn.net/kost_/article/details/13170219

代码下载地址:

http://download.csdn.net/detail/u011418185/6461377

你可能感兴趣的:(android,layout,ViewStub,include,loading,lazy)