【转】android 布局优化

前言

本篇文章为Android优化的布局部分,该部分应该是Android中很重要的,无论是在自定义控件中,还是在简单的书写布局时,都应该尽量遵循一些优化原则,这样布局的绘制效率才会更高,体验才能更好。

一 优化layout的层级

Layout结构如果太复杂,Android的绘制过程就会很复杂,measure过程就会很复杂,我分析的View绘制机制中详细介绍了整个测量、布局和绘制过程,过于复杂、嵌套的布局会造成性能问题。

1.1 避免嵌套

嵌套的 LinearLayout 可能会使得 View 的层级结构很深。使用LinearLayout时,通常我们喜欢用嵌套的布局来动态设置一个View的Visibility ,由于LinearLayout是线性的,因此即使隐藏一个View也不会影响到其它View的排列。而在RelativeLayout中,View的位 置都是相对于其它View的,因此,隐藏之后,会导致之前的View没有参考对象了,导致的相对位置改变,这时你可以使用 alignWithParentIfMissing=”true”来处理这种情况。

此外,嵌套使用了 layout_weight 参数的 LinearLayout 的计算量会尤其大,因为每个子元素都需要被测量两次。这对需要多次重复 inflate 的 Layout 尤其需要注意,比如使用 ListView 或 GridView 时。

1.2 使用merge标签优化层级

在使用了include后可能导致布局嵌套过多,出现不必要的layout节点,从而导致解析变慢。

merge标签可用于两种典型情况:

  • 布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容试图的parent view就是个FrameLayout,所以可以用merge消除只剩一个。
  • 某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。

比如,如果你有一个 Layout 是一个竖直方向的 LinearLayout,其中包含两个连续的 View 可以在别的 Layout 中重用,那么你会做一个 LinearLayout 来包含这两个 View ,以便重用。不过,当使用另一个 LinearLayout 来嵌套这个可重用的 LinearLayout 时,这种嵌套 LinearLayout 的方式除了减慢你的 UI 性能外没有任何意义。

为了避免这种情况,你可以用  元素来替代可重用 Layout 的根节点。例如:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/add"/>
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/delete"/>
</merge>

现在,当你要将这个 Layout 包含到另一个 Layout 中时(并且使用了  标签),系统会直接把两个 Button 放到 Layout 中,而不会有多余的 Layout 被嵌套。

二 使用标签重用Layout

如果你的程序 UI 在不同地方重复使用某个 Layout,那本节教你如何创建高效的,可重用的 Layout 部件,并把它们“包含”到 UI Layout 中。

为了高效重用整个的 Layout,你可以使用  和  标签把其他 Layout 嵌入当前 Layout。

三 按需载入视图

除了简单的把一个 Layout 包含到另一个中,你可能还想在程序开始后,仅当你的 Layout 对用户可见时才开始载入。

3.1 不需要立即加载的布局,设置为GONE,系统会跳过,不加载

3.2 使用ViewStub 实现按需加载

ViewStub 是一个轻量的视图,不需要大小信息,也不会在被加入的 Layout 中绘制任何东西。每个 ViewStub 只需要设置 android:layout 属性来指定需要被 inflate 的 Layout 类型。viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。

以下 ViewStub 是一个半透明的进度条覆盖层。功能上讲,它应该只在新的数据项被导入到应用程序时可见。

1 <ViewStub
2     android:id="@+id/stub_import"
3     android:inflatedId="@+id/panel_import"
4     android:layout="@layout/progress_overlay"
5     android:layout_width="fill_parent"
6     android:layout_height="wrap_content"
7     android:layout_gravity="bottom" />

载入 ViewStub
当你要载入用 ViewStub 声明的 Layout 时,要么用 setVisibility(View.VISIBLE) 设置它的可见性,要么调用其 inflate() 方法。

下面以在一个布局main.xml中加入网络错误时的提示页面network_error.xml为例。main.mxl代码如下:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent" >
 5     ……
 6     <ViewStub
 7         android:id="@+id/network_error_layout"
 8         android:layout_width="match_parent"
 9         android:layout_height="match_parent"
10         android:layout="@layout/network_error" />
11 </RelativeLayout>

1

2

3

4

5

6

7

8

9

10

11

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

    ……

    <ViewStub

        android:id="@+id/network_error_layout"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout="@layout/network_error" />

</RelativeLayout>

其中network_error.xml为只有在网络错误时才需要显示的布局

setVisibility(View.VISIBLE)方式

1 View viewStub = ((ViewStub)findViewById(R.id.stub_import));
2 viewStub.setVisibility(View.VISIBLE);
3 netErrorLayout = findViewById(R.id.net_error_layout))

inflate方式

1 View netErrorLayout = ((ViewStub) findViewById(R.id.net_error_layout)).inflate()

注意:
inflate() 方法会在渲染完成后返回给被 inflate 的视图,所以你不需要再调用 findViewById() 去查找这个元素。减少inflate的次数,也会对效率有一点提升。
而setVisible方式还需要再次findViewById找到ViewStub中的元素。

一旦 ViewStub 可见或是被 inflate 了,ViewStub 元素就不存在了。取而代之的是被 inflate 的
Layout,其 id 是 ViewStub 上的 android:inflatedId 属性。(ViewStub 的 android:id
属性仅在 ViewStub 可见以前可用)

注意:ViewStub 的一个缺陷是,它目前不支持使用  标签的 Layout

四 ListView的优化

如果你有一个包含复杂或者每个项 (item) 包含很多数据的 ListView ,那么上下滚动的性能可能会降低。本节给你一些关于如何把滚动变得更流畅的提示。
保持程序流畅的关键,是让主线程(UI 线程)不要进行大量运算。你要确保在其他线程执行磁盘读写、网络读写或是 SQL 操作等。为了测试你的应用的状态,你可以启用 StrictMode。

4.1 使用后台线程

你应该把主线程中的耗时间的操作,提取到一个后台线程中,使得主线程只关注 UI 绘画。

4.2 在 View Holder 中填入视图对象

使用convertView、
你的代码可能在 ListView 滑动时经常使用 findViewById(),这样会降低性能。即使是
Adapter 返回一个用于回收的 convertView,你仍然需要查找这个元素并更新它。避免频繁调用 findViewById()
的方法之一,就是使用 View Holder(视图占位符)设计模式。

ViewHolder 存储了标签下的每个视图。这样你不用频繁查找这个元素:

1 static class ViewHolder {
2     TextView text;
3     TextView timestamp;
4     ImageView icon;
5     ProgressBar progress;
6     int position;
7 }

然后,在 Layout 的类中生成一个 ViewHolder 对象:

1 ViewHolder holder = new ViewHolder();
2 holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
3 ...
4 convertView.setTag(holder);

这样你就可以轻松获取每个视图,而不是用 findViewById() 来不断查找视图,节省了宝贵的运算时间。

4.3 getView不要做复杂的操作

因为每一条Item移入屏幕的时候,都会调用getView,不要在getView中做复杂的操作,不要频繁的创建对象。Item点击的处理不要提前做。特别是在快速滑动的时候,会导致频繁的调用getView。

五 优化提示

尽量使用RelativeLayout,可以减少层级的嵌套。
慎用LinearLayout的layout_weight属性,可以使用RelativeLayout的centerHorizontal=”true”、toLeft、toRight代替

六 书写规范上的优化

6.1 Id的命名

为了便于识别,你可以根据自己的业务来对当前界面的资源进行命名,比如当前是登陆界面,那么你可以这样命名:
login_edit_username
login_edit_password
login_btn_submit
login_txv_forgot_pass

6.2 资源的命名

ic_action_add, ic_action_location (ActionBar Icons)
ic_play, ic_save (General Icons)
ic_tab_music, ic_tab_more (Tab Icons)

6.3 通用的资源命名

对style.xml和dimens.xml的命名可以通用的尽量通用,因为一个项目的基本视图很多都是通用的,比如ActionBar、ListView等,规范通用的命名可以很方便的移植到其它项目中。

 1 <color name="list_item_large">#FCA558</color>
 2 <color name="list_item_small">#FBA228</color>
 3 <dimen name="list_item_large">24dp</dimen>
 4 <dimen name="list_item_small">18dp</dimen>
 5 <!-- 简单ListView样式 -->
 6 <style name="list_view_style_default">
 7 <item name="android:layout_width">fill_parent</item>
 8 <item name="android:layout_height">wrap_content</item>
 9 ...
10 </style>

参考文献

best-practices-for-android-user-interface
layout-performance

时间: 2024-12-06 13:01:49

【转】android 布局优化的相关文章

Android布局优化

Android影响布局性能主要是Overdraw(过度绘制),表现在重叠不可见元素的重复绘制会产生额外的开销. Overdraw以颜色划分等级:蓝色:Overdraw1倍:绿色:Overdraw2倍:浅红:Overdraw3倍:暗红;Overdraw4倍以上(需要进行优化). Android布局优化解决措施: 1.合理选择控件 LinearLayout简单易用,效率高,但是使用范围有限. RelativeLayout较复杂,使用范围广,效率稍差. 2.去掉windows默认背景 去掉window

【转】Android布局优化之ViewStub

ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的View,与其他的控件一样,有着自己的属性及特定的方法.当ViewStub使用在布局文件中时,当程序inflate布局文件时,ViewStub本身也会被解析,且占据内存控件,但是与其他控件相比,主要区别体现在以下几点: 1.当布局文件inflate时,ViewStub控件虽然也占据内存,但是相相比于其他控

Android 布局优化工具Hierarchy Viewer的使用

网上已经有很多关于Hierarchy Viewer如何使用的文章,这里就不一步步的演示具体怎样使用了,ddna兄的<[Android工具]被忽略的UI检视利器:Hierarchy Viewer>与张兴业的<Android UI 优化--使用HierarchyViewer工具>都写的很棒. Hierarchy Viewer有两个用途,一个是用于分析当前页面视图层级,再者也能分析布局的时间统计(Measrue.Layout.Draw)所需要的具体时间,本篇主要是关注布局时间的统计功能.

Android布局优化之include、merge、ViewStub的使用

本文针对include.merge.ViewStub三个标签如何在布局复用.有效减少布局层级以及如何可以按需加载三个方面进行介绍的. 复用布局可以帮助我们创建一些可以重复使用的复杂布局.这种方式也意味着应用中任何在多个布局文件之间使用的通用布局都可以被提取出来,然后分别进行管理,使用的时候再进行组合.因此当我们在自定义一些View的时候,使用复用布局会更简单方便.在平常开发中使用可以复用的布局文件,不仅仅是因为它可以有效减少布局文件数量,更多的目的在于它更方面我们管理应用,布局复用,在更改某个组

[Android]Android布局优化之&lt;include /&gt;

转载请标明:转载于http://www.cnblogs.com/Liuyt-61/p/6602891.html ------------------------------------------------------------------------------------------- >将可复用的组件抽取出来并通过include标签使用. 作用: 将共同的组件抽取出来单独放到一个xml文件中,然后使用include标签导入公用布局. 效果:提高UI的制作和复用效率,也能保证制作的UI布

Android 布局优化

在开发过程中我们经常说性能优化,但性能优化是一个比较宽泛的概念.在Android开发中性能优化可能包括:Java代码优化, 算法优化, SQLite优化, 布局优化等.那么这篇博客就来总结并分享下Android开发中的布局优化. 布局原则 在Android UI布局过程中,通过遵守一些惯用.有效的布局原则,我们可以制作出高效且复用性高的UI,概括来说包括如下几点: 尽量多使用RelativeLayout和LinearLayout, 不要使用绝对布局AbsoluteLayout,在布局层次一样的情

android布局优化的三大标签

1.布局重用 <include /> 标签能够重用布局文件,简单的使用如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_par

Android布局优化:include 、merge、ViewStub的详细总结

本篇博客主要是对上篇博客的补充Android性能优化之UI渲染性能优化, 没有什么新东西,觉得应该是都掌握的玩意,写出来也只是自己做个小小的总结. 一.include的用法以及注意点 在开发Android布局时,我们常将一些通用的视图提取到一个单独的layout文件中,然后使用<include>标签在需要使用的其他layout布局文件中加载进来,比如我们自己App导航栏等.这样,便于对相同视图内容进行统一的控制管理,提高布局重用性. 下面我们以大部分项目中都有的头部导航栏为例,说明一下incl

Android成长日记-Android布局优化

Android常用布局 1. LinearLayout(线性布局) 2. RelativeLayout(相对布局) 3. TableLayout(表格布局) 4. AbsoluteLayou(绝对布局) 5. FrameLayout(帧布局) 低--------------使用量------------------à高 4->3->5->1->2 Android布局原则 (1) 尽量多使用LinearLayout和RelativeLayout,不要使用AbsoluteLayout

Android布局优化之层级优化

程序的每个组件和 Layout 都需要经过初始化.布局和绘制,如果布局嵌套层次过深,就会导致加载操作更为耗时,更严重的话还可能导致内存溢出.本节我们学习使用两个工具来检查和优化 Layout. HierarchyViewer 该工具位于Android SDK tools中,使用HierarchyViewer可以分析正在运行app的布局,从而打破影响布局性能的瓶颈. HierachyViewer通过选择运行在模拟器或真机上的进程来工作,并通过布局树来展示.上面每个标识代表布局的Measure.La