Android系统的UI和内存优化策略

本文从以下3部分介绍:

布局优化

内存优化

使用各种工具来进行分析,优化

 

一.布局优化

一个好的UI不仅应该具有良好的视觉效果,更应该具有良好的使用体验。

1.1. Android UI渲染机制

Android 系统提供了检测UI渲染时间的工具,打开“开发者选项”,选择“profile GPU Rendering”,并选中“on screen as bars”的选项,这时候在屏幕上将显示一些条形图。

每一条柱状线都包含三部分:

蓝色代表测量绘制Display list的时间,

红色代表OpenGL渲染Display List所需要的时间,

黄色代表cpu等待Gpu处理的时间,

中间的绿色横线代表VSYNC时间16ms,需要尽量将所有条形图都控制在这条绿线之下。

1.2. 避免Overdraw

android系统在开发者选项中提供了这样一个检测工具——“Enable GPU Overdraw”。激活后可通过界面上的颜色来判断Overdraw的次数,从而尽量优化绘图层次,尽量增大蓝色的区域,减少红色区域。

1.3. 优化布局层级

Android中,系统对view进行测量,布局和绘制时,都是通过对view数的遍历来进行操作的,如果一个view树的高度太高,就会严重影响测量,布局和绘制的速度,因此优化布局的第一个方法就是降低view树的高度,文档中建议不宜超过10层。通过扁平的RelativeLayout替代LineralLayout,就是为了减少嵌套,减少数的高度。

1.4. 避免嵌套过多无用布局

1.4.1. 使用<include>标签重用Layout

比如一个应用的topbar,bottombar,可以用<include>定义一个通用的UI

在代码中,将layout_widthlayout_height设置为0 dp,这样可使得开发者在使用时对宽高进行赋值,否则将无法看见这个界面。

重点:如果你需要在<include>标签中覆盖类似原布局中Androidlayout_XXXX的属性,就必须在<include>标签中同时指定Androidlayout_widthAndroidlayout_height属性。

1.4.2. 使用<viewStub>实现view的延迟加载

<viewStub>标签与设置view.GONE这种方式来隐藏一个view有什么区别呢?的确,他们的共同点都是初始时不会显示,但是<viewStub>标签只会在显示时,才去渲染整个布局,而view.GONE,在初始化布局树的时候就已经添加在布局树上了,相比之下<viewstub>标签的布局具有更高的效率。

1.5. Hierarchy viewer

通常情况下,Hierarchy viewer无法在真机上进行使用,她只能在工厂的Demo机和模拟器上使用,即非加密过的设备。Romain Guy提供了一个开源项目view server,通过这个程序可以让普通的手机也能使用Hierarchy viewer,http://github.com/romainguy/ViewServer

启动H v后,重点关注IDcontentFrameLayout的分支,这也是setContentView()所设置的内容。

三个不同颜色的小圆点,用来表示绘制的效率,绿 红分别代表好 差三种不同的绘制效率。

通过H v工具,可以很快在视图树中找到冗余的布局,从而有目的地优化布局。

二.内存优化

2.1. 什么是内存

由于Android应用的沙箱机制,每个应用所分配的内存大小是有限的,内存太低就会触发LMK——low memory killer机制。通常情况下我们所说的内存是指手机的RAM,它包括以下几个部分。

寄存器(Registers

速度最快的存储场所,因为寄存器位于处理器内部,在程序中无法控制

栈(stack

存放基本类型的数据和对象的引用,但对象本身不存在栈中,而是存放在堆中

堆(Heap

堆内存用来存放油new创建的数组和对象。在堆中分配的内存,由Java虚拟机的自动垃圾回收器(GC)来管理。

静态存储区域(static field

静态存储区域就是指在固定的位置存放应用程序运行时一直存放的数据,Java在内存中专门划分一个静态存储区域来管理一些特殊的数据变量如静态的数据变量。

常量池(Constant Pool

JVM虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型 字段和方法的符号引用。

在这些概念中最容易搞错的就是堆和栈的区别。当定义一个变量,Java虚拟机就会在栈中为该变量分配内存空间,当该变量作用域结束后,这部分内存空间会马上被用作新的空间进行分配。如果使用new的方式创建一个变量,那么就会在堆中为这个对象分配内存空间,即使该对象的作用域结束,这部分内存也不会立即被回收,而是等待系统GC进行回收。堆的大小随着手机的不断发展而不断变大。在程序中,可以获得堆的大小,所谓的内存分析,正是分析Heap中的内存状态。

2.2. 获取Android系统内存信息

2.2.1. Process Stats

P SKK上一个新增的一个系统内存监控服务,可以通过“setting-Developer-options-process stats”来开启该功能的界面。

2.2.1.1. Meminfo

Meminfo也是系统上的一个非常重要的内存监视工具,可以通过在Settings-APPs-Running中打开这一界面

2.3. 内存回收

Java对于C C++这类语言最大的优势就是不用手动管理系统资源,Java创建了垃圾收集器线程来自动进行资源的管理。大大降低了程序开发人员对内存管理的繁琐工作。但难免会存在部分对象忘记回收的现象发生,造成内存泄漏。

2.4. 内存优化实例

分别从Bitmap和代码两个角度来对内存进行优化。

2.4.1 Bitmap优化

Bitmap是造成内存占用过高甚至是OOM的最大威胁。下面是一些Bitmap的小技巧。

使用适当分辨率和大小的图片

例如在图片列表界面可以使用图片的略缩图thumbnails,而在显示详细图片的时候再显示原图;或者在对图像要求不高的地方,尽量降低图片的精度。

使用图片缓存

通过内存缓存和硬盘缓存可以更好地使用Bitmap

2.4.2. 代码优化

从代码的实现方式上也可以对内存进行优化,这里同样总结了一些小的技巧。

对常量使用static修饰符

使用静态方法,静态方法会比普通方法提高15%左右的访问速度

减少不必要的成员变量,这点在Android lint工具上已经集成检测了,如果一个变量可以定义为局部变量,则不要定义为成员变量。

减少不必要的对象,使用基础类型会比使用对象更加节省资源,同时更应该避免频繁创建短作用域的变量。

尽量不要使用枚举 少量迭代器

cursor receiver sensor file等对象,要非常注意对他们的创建 回收与注册 解注册

避免使用IOC框架,IOC通常使用注解 反射来进行实现,虽然现在Java对反射的效率已经进行了很好额优化,但大量使用反射依然会带来性能的下降。

使用RenderScript OpenGL来进行非常复杂的绘图操作

使用surface view来替代view进行大量频繁的绘图操作

尽量使用视图缓存,而不是每次都执行inflate()方法解析视图

三.Lint工具

Android studio一个代码提示工具,它可以给你的布局 代码提供非常强大的帮助,应养成写完代码后检查lin提示的习惯。

四.使用Android studiomemory monitor工具

M M工具是AS自带的一个内存监视工具,可以很好地帮助我们进行内存实时分析。

五.使用Traceview 工具优化APP性能

Traveview是一个Android下的可视化性能调查工具,它用来分析TraceView日志。

5.1生成traceview日志的两种方法

5.1.1. 通过代码生成精确范围的Traceview日志

5.1.2. 通过Android device monitor生成Traceview日志

5.2. 打开traceview日志

5.3. 分析traceview 日志

5.3.1. profile区域

六.使用MAT工具分析APP内存状态

MAT工具是一个分析内存的强力助手

6.1. 生成HPROF文件

6.2. 分析HPROF文件

七.使用Dumpsys命令分析系统状态

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值