您的位置:首页 > 移动开发 > Android开发

Android性能优化--Layout优化篇

2015-07-13 23:18 495 查看
Layout是Android程序的用户体验的最为直接的关键部分。本文将讲述如何使Layout占用尽可能少的内存,尽可能流畅。


一. 优化Layout层级

Android SDK中有个工具Hierarchy Viewer,位于<sdk>/tool/目录下,用来分析应用程序Layout,快速定位Layout的性能瓶颈。


(1)使用RelativeLayout代替LinearLayout

<?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">

<ImageView
android:id="@+id/listitem_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/listitem_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textview1" />
<TextView
android:id="@+id/listitem_timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textview2" />
</LinearLayout>
</LinearLayout>


以上布局,通过Hierarchy Viewer查看,可得到如下图:


!

上图是一个3层结构,点击其中的项可以查看每个步骤的花费时间,其中

一个完整的视图渲染时间为:

测量:0.977ms

布局:0.167ms

绘制:2.717ms

布局优化:

上述LinearLayout布局内还有一个LinearLayout布局的嵌套,会导致性能变慢,解决方法是将布局扁平化,采用RelativeLayout布局,布局由三层变成两层:

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

<ImageView
android:id="@+id/listitem_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/listitem_text"
android:layout_below="@id/listitem_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textview1" />
<TextView
android:id="@+id/listitem_timestamp"
android:layout_toRightOf="@id/listitem_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textview2" />
</RelativeLayout>




现在的渲染时间:

测量:0.598ms

布局:0.110ms

绘制:2.146ms

看起来只有较小的优化,列表的每一项都有效,时间优化会有叠加效应。

二. 重用Layout

(1)< include >标签

将所有布局中的通用部分提取出来,成为单独的模块化布局,当其他布局需要使用时,通过< include >标签来引入布局,例如常见的有应用程序的底部、菜单等。

如下是activity_main.xml布局,代码如下:

<RelativeLayout       xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />

<include layout="@layout/foot.xml"/>

</RelativeLayout>


其中include的布局foot.xml代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<Button
android:id="@+id/menu_first"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:text="first" />
<Button
android:id="@+id/menu_second"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/menu_first"
android:text="second" />
<Button
android:id="@+id/menu_third"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/menu_second"
android:text="third" />

</RelativeLayout>


(2)< merge >标签

在嵌套Layout中取消UI层级中冗余的ViewGroup, 加快性能。上述的foot.xml,可以采用< merge >优化:

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

<Button
android:id="@+id/menu_first"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:text="first" />
<Button
android:id="@+id/menu_second"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/menu_first"
android:text="second" />
<Button
android:id="@+id/menu_third"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/menu_second"
android:text="third" />

</merge>


三. 按需加载Layout

Layout中有些细节的布局,并不需要一开始就全部加载,而是在真正需要的时候才加载,从而提高UI布局的渲染速度。

(1)< viewstub >标签

viewstub 是轻量级视图,无需大小参数,也不会被加入Layout中渲染,只需要指定android:layout属性来指定需要被inflate的Layout类型。

<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />


需要时加载viewstub,方法如下:

//方法1
((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
//方法2
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();


说明:

ViewStub可见前,android:id属性和ViewStub 可用

ViewStub可见后,id属性和ViewStub 不可用,android:inflatedId 属性与android:layout代替之。

(2)GONE属性

对于不需要马上加载的view,也可以先将其设置为GONE。在需要的时候将再设置VISIBLE即可

四. 优化ListView

(1)利用convertView 以及 viewHolder

ListView 滑动时需要频繁使用 findViewById(),这样大大降低性能。为避免频繁调用,使用viewHolder设计模式

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
}

static class ViewHolder {
TextView text;
TextView timestamp;
ImageView icon;
}


(2)异步加载

有时当ListView中加载大量的较为复杂的布局与图片时,即使使用 convertView 和 viewHolder还是卡顿,则可以考虑异步加载方式。

只有当ListView停止滑动时,才开启新线程加载所需数据;

使用getFirstVisiblePosition 和 getLastVisiblePosition 方法来显示 item

耗时任务异步进行,getView()只执行可快速完成的代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: