首页 > 代码库 > Android App性能优化(一)之布局优化
Android App性能优化(一)之布局优化
当创建复杂布局的时候,我们会在xml 文件中添加大量的ViewGroup和View。伴随着每次迭代,View树的层次越来越深,界面加载速度越来越慢,消耗的内存也越来越多。当您的程序出现加载时短暂黑屏或横竖切换时短暂黑屏,抑或如内存溢出(OOM)之类的问题时,没准您的程序需要优化了。
那么如何让程序运行速度更快?响应更敏捷?优化布局是一个最基本的方法,本文将介绍最基本的优化布局方法。
1.使用ViewStub实现View的延迟加载。
很多情况下,xml布局文件中的部分View初始状态是设置为不显示的(android:visible="invisible"或"gone")的。如您的代码中存在这种设置的View,您可以尝试使用ViewStub.
Android开发文档中对ViewStub的介绍如下:
http://developer.android.com/reference/android/view/ViewStub.html
“ViewStub”是一种不可见并且大小为0的试图,可以延迟到运行时加载(Inflate)布局资源。当ViewStub被设置为可见或者调用inflate()方法时,才会加载布局资源。然后ViewStub便被加载的布局替代。
现在我们使用Eclipse创建一个新工程,默认Fragment的布局文件如下:
<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="com.example.testlayout.MainActivity$PlaceholderFragment" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Inflate View Stub" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_below="@id/button" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</LinearLayout>
</RelativeLayout>
如上可见,LinearLayout中嵌套了多个子View。如果在Activity载入的时候不需要立即显示这部分内容,我们就可以使用ViewStub将这LinearLayout替换掉。
修改后的布局如下:
<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="com.example.testlayout.MainActivity$PlaceholderFragment" >
<Button <!-- 点击该Button后加载ViewStub -->
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Inflate View Stub" />
<ViewStub
android:id="@+id/viewStub"
android:inflatedId="@+id/view_stub_layout" <!-- 将会替换掉子布局中的最外层ViewGroup的id -->
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/button"
android:layout="@layout/view_stub_layout"/> <!-- 加载的子布局 -->
</RelativeLayout>
其中省去的LinearLayout放入新的布局文件view_stub_layout.xml中,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</LinearLayout>
最后完成我们的Java文件,当点击Button时,执行以下代码:
private void showViewStub() {
ViewStub stub = (ViewStub) mRootView.findViewById(R.id.viewStub);
if (stub != null) {
Log.i("xzy", "stub is not null");
// stub.setLayoutResource(R.layout.view_stub_layout); //如果布局文件中未设置android:layout="@layout/view_stub_layout",可以这样设置子布局
stub.inflate();
View view = (View) mRootView.findViewById(R.id.linearLayout);
if (view != null) {
view.setBackgroundColor(Color.RED);
}
} else {
Log.i("xzy", "stub is Null");
}
}
ViewStub加载完之后将变为Null,此后就无法通过ViewStub对象加载子布局了,所以不会重复加载。