`
cnetwei
  • 浏览: 174423 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

【转】Android系统中的UI优化

 
阅读更多

1、RelativeLayout 优于 LinearLayout

Android中最常用LinearLayout来表示UI的框架,而且也是最直观和方便的方法,例如创建一个UI用于展现Item的基本内容,如图所示:


线框示意图:


通过LinearLayout实现以上UI的代码:

<LinearLayout xmlns:
  android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip">

 <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_marginRight="6dip"
        android:src="@drawable/icon" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent">

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:text="My Application" />

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1" 
            android:singleLine="true"
            android:ellipsize="marquee"
            android:text="Simple application that shows how to use RelativeLayout" />
    </LinearLayout>
</LinearLayout>

 

尽管可以通过Linearlayout实现我们所预想的结果,但是在这里存在一个优化的问题,尤其是针对大量Items时。比较RelativeLayout和LinearLayout,它们在资源利用上,前者会占用更少的资源而达到相同的效果,以下是用RelativeLayout来实现同样UI的代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip">
    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="6dip"
        android:src="@drawable/icon" />

    <TextView
        android:id="@+id/secondLine"
        android:layout_width="fill_parent"
        android:layout_height="26dip" 
        android:layout_toRightOf="@id/icon"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:text="Simple application that shows how to use RelativeLayout" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/icon"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_above="@id/secondLine"
        android:layout_alignWithParentIfMissing="true"
        android:gravity="center_vertical"
        android:text="My Application" />
</RelativeLayout>

使用RelativeLayout时有一点需要注意,因为它内部是通过多个View之间的关系而确定UI框架,那么当其中某一个View因为某些需要调用GONE来完全隐藏掉后,会影响与其相关联的Views。Android为我们提供了一个属性 alignWithParentIfMissing 用于解决类似问题,当某一个View无法找到与其相关联的Views后将依据alignWithParentIfMissing的设定判断是否与父级View对齐。

你可以通过Hierarchy Viewer查看两种布局方案的View层级图,RelativeLayout明显优于LinearLayout。

2、UI资源的复用

定义Android Layout(XML)时,有四个比较特别的标签是非常重要的,其中有三个是与资源复用有关,分别是:<viewStub/>,<merge/>和<include/> ,可是以往我们所接触的案例或者官方文档的例子都没有着重去介绍这些标签的重要性。

<include/> :可以通过这个标签直接加载外部的xml到当前结构中,是复用UI资源的常用标签。使用方法:将需要复用xml文件路径赋予include标签的Layout属性,示例如下:

<include android:id="@+id/cell1" layout="@layout/ar01"/>
<include android:layout_width="fill_parent" layout="@layout/ar02"/>

< viewStub/ > 此标签可以使UI在特殊情况下,直观效果类似于设置View的不可见性,但是其更大的意义在于被这个标签所包裹的Views在默认状态下不会占用任何内存空间。viewStub通过include从外部导入Views元素。使用方法:通过android:layout来指定所包含的内容,默认情况下,ViewStub所包含的标签都属于visibility=GONE。viewStub通过方法inflate()来召唤系统加载其内部的Views。
示例:

<ViewStub android:id="@+id/stub"
    android:inflatedId="@+id/subTree"
    android:layout="@layout/mySubTree"
    android:layout_width="120dip"
    android:layout_height="40dip" />

<merge/> :该标签在优化UI结构时起到很重要的作用,目的是通过删减多余或者额外的层级,从而优化整个UI Layout的结构。以下将通过一个例子来了解这个标签实际所产生的作用,这样可以更直观的了解 &lt;merge/&gt;的 用法。

建立一个简单的Layout,其中包含两个Views元素:ImageView和TextView,默认状态下我们将这两个元素放在FrameLayout中。其效果是在主视图中全屏显示一张图片,之后将标题显示在图片上,并位于视图的下方。以下是xml代码:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ImageView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" 
        android:scaleType="center"
        android:src="@drawable/golden_gate" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dip"
        android:layout_gravity="center_horizontal|bottom"
        android:padding="12dip"
        android:background="#AA000000"
        android:textColor="#ffffffff"
        android:text="Golden Gate" />
</FrameLayout>

以上布局的效果图如下:


启动 tools> hierarchyviewer.bat工具查看当前UI结构视图:


 我们可以很明显的看到由红色线框所包含的结构出现了两个framelayout节点,很明显这两个完全意义相同的节点造成了资源浪费(这里可以提醒大家在开发工程中可以习惯性的通过hierarchyViewer查看当前UI资源的分配情况),那么如何才能解决这种问题呢?(就当前例子是如何去掉多余的frameLayout节点),这时候就要用到 &lt;merge/&gt; 标签了,我们将上边xml代码中的framLayout替换成merge:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <ImageView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" 
        android:scaleType="center"
        android:src="@drawable/golden_gate" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dip"
        android:layout_gravity="center_horizontal|bottom"
        android:padding="12dip"
        android:background="#AA000000"
        android:textColor="#ffffffff"
        android:text="Golden Gate" />
</merge>

运行程序后在Emulator中显示的效果是一样的,可是通过hierarchyviewer查看的UI结构是有变化的,当初多余的 FrameLayout节点被合并在一起了,或者可以理解为将merge标签中的子集直接加到Activity的FrameLayout根节点下了。(这里需要提醒大家注意:所有的Activity视图的根节点都是FrameLayout)。如果你所创建的Layout并不是用FramLayout作为根节点(而是应用LinerLayout等定义root标签),就不能应用上边的例子 通过merge来优化UI结构了。

除了上边的例子外,meger还有另外一个用法:当应用Include或者ViewStub标签从外部导入xml结构时,可以将被导入的xml用merge作为根节点,这样当被嵌入父级结构中后可以很好的将它所包含的子集融合到父级结构中,而不会出现冗余节点。
另外有两点需要特别注意:
A.<merge/>只可以作为xml layout的根节点;
B.当需要扩充的xml layout本身是由merge作为根节点的话,需要将被导入的xml layout置于viewGroup中,同时需要设置attachToRoot为True。(更多说明请参见inflate()文档)

3、使用工具 hierarchyViewer 和 Layout Opt.

前边已经介绍了如何通过Layout优化系统资源,减少不必要的资源占用。基于如何在合理利用资源的前提下,更进一步的提升视觉表现力。这里所提到的视觉表现力并不是指直观所看到的视觉效果,而是性能的提升。
这里将包含两个主要内容:

  • Drawing(绘制的刷新率)
  • Startup Time (启动Activities的时间)

以上两个性能的优化都将依赖于 Window backGround drawable功能设置。
通过Window backGround标识会对部分人产生一定的误解,其实每次通过setContentView()来显示预先配置的界面时,Android仅仅是将你所创建的Views添加到Activiy的Window中。而且这个Window并不仅仅包含你所创建的Views,还包括Android为Activity预置的元素。通过Emulator运行你的程序,然后通过Hierarchy Viewer查看当前程序UI架构Root节点 DecorView,这个是Android额外添加的最顶层的节点。



实际上Window background drawable是由DecorView决定的。可以在Activity中调用getWindow().setBackgroundDrawable()方法来设置DecorView的background drawable。这里要特别注意这个方法是针对当前版本的Android平台,以后可能会因为版本的更新或不同的硬件设备而改变。(目前我们仅针对 G1,如果在其它环境下测试需要小心验证)
如果目前正在使用android默认的标准Themes,那么在调用getWindow().setBackgroundDrawable()方法之后,这个background drawable将会影响你的activities。通过一个例子来直观的比较性能提升的效果:

通过上边这个截图可以看到保持activity的redraw模式下,当前的FPS为39帧 /每秒,大概相当于25毫秒/每帧。由于这个例子中将ImageView设为全屏显示,并且完全覆盖了activity的背景,所以background drawable占用了不必要的计算资源。下边创建一个新的Theme并且应用在Activity中,创建res/values/theme.xml, XML的内容:

<resources>
    <style name="Theme.NoBackground" parent="android:Theme">
        <item name="android:windowBackground">@null</item>
    </style>
</resources>

同时也需要修改AndroidMainfest.xml文件,将上边所创建的Theme应用到Activity中,格式为:

<application android:icon="@drawable/icon" android:label="@string/app_name">
	<activity android:name=".EggImageViewer"
     android:label="@string/app_name"
     android:theme="@style/Theme.NoBackground">
 	    <intent-filter>
	        <action android:name="android.intent.action.MAIN" />
	        <category android:name="android.intent.category.LAUNCHER" />
	    </intent-filter>
	</activity>
</application>

(也可以将Theme应用于<Application />标签中)完成上边的修改后,再来看看当前的FPS发生了什么变化:

 

FPS可以增大到60+,性能得到如此大的提升,是不是比较难以置信呢?由此可以明白当应用MapView或者WebView全屏显示的应用程序时,可以借用这个简单设置的方法,来提升整体的性能。
通过上边的例子可以直观的了解window background drawable的优化方法,并且根据比较可以很明显的看到设置前后的性能对比,希望这个简单的技巧可以给你的应用带来帮助。
另外基于这个技巧的应用,还可以延展出另外一个优化功能。对于某些需要全屏显示的应用程序,可以通过Theme定义Window’s background的图片,从而提高Activity的启动速度。毕竟无需建立一个ImageView作为自定义的背景,而重复叠加在Activity window background。
实现方法:
创建 res/drawable/background_res.xml

<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/shelf_panel"
    android:tileMode="repeat" />

创建res/values/theme.xml

<resources>
    <style name="Theme.Shelves" parent="android:Theme">
        <item name="android:windowBackground">@drawable/background_res</item>
        <item name="android:windowNoTitle">true</item>
    </style>
</resources>

往往一些看似简单的方法,却能起到非常大的作用。还希望大家在实践中能不断的挖掘出非常实用的技巧,然后与你周围的人共享你的发现,同时在大家共同的见证下可以完善你的想法!

源码附件:

 

 

 

 

  • 大小: 6.4 KB
  • 大小: 2.4 KB
  • 大小: 63.6 KB
  • 大小: 7.1 KB
  • 大小: 24.4 KB
  • 大小: 6.8 KB
  • 大小: 6.8 KB
分享到:
评论

相关推荐

    Android优化技术详解

    《Android优化技术详解》分为12章,第1章讲解了Android系统的基础知识;第2章讲解了Android核心框架;第3章详细讲解了为什么要优化;第4章详细讲解了uI布局优化的基本知识;第5章详细讲解了Andro 资源太大,传百度...

    android 定制系统(多卡系统)

    android 定制系统(多卡系统)包含android四卡、系统UI优化等。

    uiautomatorviewer工具更新优化适配Android8.0以上系统

    sdk文件,通过更新SDK-tools/lib路径里的uiautomatorviewer.jar文件,适配Android 8.0以上版本来获取被测app元素控件读取,方便自动化元素定位。

    Android UI规范

    Android UI设计规范文档 1 设计原则 2 风格 2.1 设备和显示 Android 驱动了数百万的手机、平板和其它设备,兼容了各种屏幕宽度和比例。利用 Android 灵活的布局系统,您可以创造出从平板到手机都看起来很优雅的应用...

    车载Android操作系统快速倒车启动技术研究.pdf

    硬件实现是通过在CPU和LCD显示屏之间添加一个TW8816芯片,该芯片有两路视频输入和一路视频输出接口,分别是CPU的DISP接口传输出的Android系统UI画面信号和倒车摄像头传输出的CVBS视频画面信号。 然而,当前的技术...

    Android性能优化技术在某体重管理APP中的应用研究.pdf

    Android性能优化技术在某体重管理APP中的应用研究 Android性能优化技术是 Android 应用开发中一个非常重要的方面。随着 Android 操作系统的普及, Android 应用程序的数量也在不断增加。为了在众多应用程序中...

    Litho:在 Android 上构建高效 UI 的声明式框架-开源

    通过将其布局系统与传统的 Android View 系统解耦,Litho 可以摆脱 Android 强加的 UI 线程约束。 Litho 使用 Yoga 进行布局并自动减少您的 UI 包含的 ViewGroup 的数量。 除了 Litho 的文本优化之外,这还允许更小...

    Android应用开发揭秘(pdf )

     在Android中如何使用语音服务和Google Map Apl? Android如何访问摄象头、传感器等硬件的APl?  如何时行Widget开发?如何用各种Android组件来打造漂亮的UI界面?  Android如何解析XML数据?又如何提高解析速度和...

    《Android应用开发揭秘》附带光盘代码.

     15.6 AndroidUI优化  15.7 其他优化  15.7.1 zipalign  15.7.2 图片优化  15.8 小结  第五部分 扩展篇  第16章 Android NDK开发  16.1 AndroidNDK简介  16.2 安装和配置NDK开发环境  16.2.1 系统和软件...

    深入Android应用开发 核心技术解析与最佳实践

    第14章分析了Android系统的启动过程;第15章讲解了Android的系统管理原理,包含内存管理、应用管理、电源管理、系统管理,以及系统的还原、升级、配置和备份等多方面的内容,能帮助开发者从一个更高的视角去理解...

    Android技术总结.doc

    5.2 UI优化 Android应用程序的UI性能优化可以通过使用缓存、优化布局和避免过度绘制等方法来实现。 六、Android测试和调试 6.1 JUnit测试 Android提供了JUnit测试框架,用于测试Android应用程序的正确性和可靠性...

    基于Android的智能小车控制系统软件设计与开发.pdf

    本文设计和开发了一种基于Android的智能小车控制系统,旨在解决智能小车自动驾驶过程中存在的诸多问题。该系统采用Android端控制系统作为上位机,与搭载在智能小车主体上的主控平台进行通信连接,使用摄像头采集图像...

    Android应用开发揭秘pdf高清版

    15.6 AndroidUI优化 15.7 其他优化 15.7.1 zipalign 15.7.2 图片优化 15.8 小结 第五部分 扩展篇 第16章 Android NDK开发 16.1 AndroidNDK简介 16.2 安装和配置NDK开发环境 16.2.1 系统和软件需求 16.2.2 NDK开发...

    深入Android应用开发 核心技术解析与最佳实践.z01

    第14章分析了Android系统的启动过程;第15章讲解了Android的系统管理原理,包含内存管理、应用管理、电源管理、系统管理,以及系统的还原、升级、配置和备份等多方面的内容,能帮助开发者从一个更高的视角去理解...

    Android开发案例驱动教程 配套代码

    9.4 Android系统内置Intent 199 本章小结 201 第10章 数据存储 203 10.1 健康助手案例 203 10.2 Android数据存储概述 205 10.3 本地文件 205 10.3.1 访问SD卡 207 10.3.2 访问应用文件目录 212 10.4 SQLite...

    基于Android的小型房屋租赁系统(含万字详细文档)

    Android小型房屋租赁管理系统采用B/S结构,MVC软件开发模式,使用Android布局技术完成UI的设计,基于Java语言开发,MYSQL数据库完成,在不同型号的设备模拟器上测试通过。系统客户端实现了用户注册登录,发布房屋...

    [教程] Rom 优化小技巧

    在 Android 系统中,ROM 优化是一项非常重要的工作。通过对 ROM 的优化,可以提高系统的性能、速度和整体体验。在这篇文章中,我们将介绍 19 种 ROM 优化小技巧,帮助您快速优化您的 Android 设备。 1. 强制把 Home...

    《Android应用开发揭秘》源码

     15.6 AndroidUI优化  15.7 其他优化  15.7.1 zipalign  15.7.2 图片优化  15.8 小结  第五部分 扩展篇  第16章 Android NDK开发  16.1 AndroidNDK简介  16.2 安装和配置NDK开发环境  16.2.1 系统和软件...

    浅析安卓(Android)的性能优化

    Android性能的优化主要分为两点 1、布局优化 2、内存优化 布局优化 首先来看一下布局优化,系统在渲染UI的时候会消耗大量的资源,所以,对布局的优化就显得尤...在Android系统中,系统对View进行测量、布局、绘制的时

Global site tag (gtag.js) - Google Analytics