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 以及 viewHolderListView 滑动时需要频繁使用 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()只执行可快速完成的代码。
相关文章推荐
- Android四大组件之Activity .
- Android 关于Service的一个很好的简介
- android双屏显示的一些修改与尝试
- FragmentStatePagerAdapter第二次加载时不能显示其界面的原因及解决办法
- Android平台根目录文件
- Android开发之监听手机来电
- Android开发之一分钟教你使用双向滑动菜单
- android 自定义TextView删除线
- Android自定义圆形图片按钮
- Android组件的布局属性
- Android 输入管理服务-输入事件到达之后的处理流程
- Android RecyclerView 使用完全解析 体验艺术般的控件
- [android API 学习]View 的getLeft(),getX()和getTranslationX()
- android开发环境搭建(for 驱动开发人员)
- android launcher
- Android学习笔记(十)
- android ExpandableListView二级列表
- Android简化xml sax解析
- Android中ImageButton边框完全填充
- Android(java)学习笔记128:使用proguard混淆android代码