Android性能优化

基础原理

绘制原理(16ms原则):Android系统每隔16ms发出VSync信号,触发对UI进行渲染,这就意味着Android系统要求每一帧都要在16ms这个时间内绘制渲染完成,从而保证流畅的用户体验。

UI绘制机制:CPU和GPU是我们智能手机的标配,而绝大多数的画面渲染都依赖这两个硬件。CPU负责计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等操作;GPU负责栅格化操作,将UI元素绘制到屏幕上,所谓栅格化即把Button、Shape、Path、Bitmap等组件拆分到不同的像素上进行显示,完成绘制工作,这个操作很耗时,所以引入GPU可以加速栅格化的操作。具体在Android系统中,文字的显示是先经过CPU换算成纹理(Texture),再传给GPU渲染;而图片的显示是经过CPU计算加载到内存中,再传给GPU渲染;动画的显示是结合图片和文字的过程。

绘制优化

过度绘制的意思是屏幕上的某一个像素在同一帧的时间内被绘制了多次。

1、避免过度绘制Overdraw

具体优化方案:

(1)移除系统默认的window背景颜色:由于activity的Theme带有默认的背景颜色,会导致我们新创建的activity默认带有背景颜色,可以把背景颜色去除,减少一次绘制。

(2)移除嵌套布局中相同的背景颜色: 如果同时存在多个布局层叠的情况,可以考虑只对最上层的布局设置背景颜色,不用每个子布局或子控件都设置背景颜色,过多相同的背景颜色层叠会导致过度绘制;

过度绘制等级

2、降低onDraw()的复杂度

(1)避免在onDraw()中创建新的局部对象:因为onDraw()方法在绘制时可能会被频繁调用,会产生大量的临时对象,占用过多的内存,而且会频繁触发GC消耗系统性能。

(2)避免在onDraw()中执行耗时操作:因为在onDraw()中执行耗时操作会抢占CPU的时间片,导致绘制过程不流畅,应该把耗时操作放到子线程中。

3、常用的检测过度绘制工具

(1)Show GPU Overdraw:直接开启开发者调试中的“调试GPU过度绘制”选项,可以在屏幕上直观看到页面过度绘制的情况。

(2)ProfileGPU Rendering:开启GPU呈现模式之后,当你的应用程序在运行时,你会看到一排柱状图在屏幕上,从左到右动态地显示,每一个垂直的柱状图代表一帧的渲染,越长的垂直柱状图表示这一帧需要渲染的时间越长。随着需要渲染的帧数越来越多,他们会堆积在一起,这样你就可以观察到这段时间帧率的变化。


布局优化

优化的本质:尽量减少页面布局的层级。

1、选择合适的ViewGroup布局

性能耗费低的布局 = 功能简单 = FrameLayout、LinearLayout
性能耗费高的布局 = 功能复杂 = RelativeLayout
嵌套所耗费的性能 > 单个布局本身耗费的性能

(1)如果使用LinearLayout、 FrameLayout或者RelativeLayout都能实现相同层级的布局,尽量使用LinearLayout和FrameLayout,因为RelativeLayout加载时会相对比较复杂,增加性能开销;

(2)如果实现相同的布局,使用LinearLayout或FrameLayout需要嵌套实现,而使用RelativeLayout不需要嵌套,尽量使用RelativeLayout,避免加深Layout层级;

(3)尽量不要嵌套使用RelativeLayout;

(4)尽量不要在嵌套的LinearLayout中使用weight属性;

(5)采用自定义View代替复杂嵌套的深层级布局(在业务需求、无法优化情况下);

2、使用布局标签

(1) <merge>标签:使用该标签可以减少布局的层级, <merge>标签可以作为被引用布局的根标签,替换掉不必要的根布局,通常配合<include>标签使用;

(2)<include>标签:使用该标签可以增加布局的复用性,把一些常用的公共布局抽取出来,方便其它布局引用;

(3)<ViewStub>标签:使用该标签来加载一些默认不显示的布局,它是一个轻量级且默认不可见的视图,可以根据需求动态加载一个布局,达到惰性加载的效果,一般用于加载网络请求失败后的页面;

3、常用的检查布局的工具

(1)Hierarchy Viewer:方便查看页面布局的结构;

(2)Layout Inspector:方便查看页面布局的结构,在AS3.0以上版本才有集成;

(3)Lint:Android Studio提供的代码扫描分析工具;


内存优化

1、Android的内存管理机制

Android系统内存分配与回收方式

(1)内存分配:Android中的内存分配是弹性的,系统会根据当前设备的性能参数、RAM空间大小自动为每个进程分配一定的内存空间,并随着进程的不断运行自动分配额外的内存空间,但不会超过最大内存限制空间。也就是说Android中的内存分配策略是尽可能让更多的进程存活在内存中,保证重新打开进程时能快速响应,提高用户的体验。

(2)内存回收:当内存紧张时,Android系统会根据进程优先级的高低杀死一些进程,释放内存空间;在正常情况下,后台进程和空进程都可能会被系统杀死,后台进程采用LRUCache的缓存算法,当队列满时会杀死最早创建和最少使用的进程,而空进程随时会被系统杀死;当内存不足的情况下,系统才会考虑回收前台进程、可见进程、服务进程三种进程,并按优先级高低进程回收。同时系统为了保证尽可能让更多的进程存活在内存中会优先杀死那些占用内存比较多的进程,因此消耗内存越少的进程越容易存活下来。

2、内存优化方案

1、珍惜Service资源:当Service完成任务后,一定要记得停止它,尽量使用IntentService代替Service,IntentService的好处是当任务完成后会自动停止Service,同时内部维护了一个Thread线程可以执行耗时操作。

2、当UI不可见时释放资源:当前界面UI不可见时,应该释放掉该UI上所占用的资源,可以增加系统缓存进程的能力。可以在Activity中重写onTrimMemory()回调方法,并且当回调级别level为TRIM_MEMORY_UI_HIDDEN时,表明当前Activity的UI已经隐藏,可以进行UI资源的释放了。

3、避免Bitmap滥用:可以根据当前屏幕分辨率对Bitmap中的数据进行压缩,同时采用软引用+LRUCache缓存算法来管理Bitmap,软引用在内存不足时会被GC回收,释放内存。

4、使用优化的数据容器:尽量使用SparseArray代替HashMap。HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作,而SparseArray更加高效在于它避免了对key的自动装箱,从而避免装箱后的解箱。同时尽量少使用枚举类型、尽量使用StringBuilder进行字符串的拼接,因为String对象的字符串拼接会导致大量中间字符串的产生,GC需要额外回收这些中间字符串。

5、避免使用依赖注入框架

6、使用多进程


性能检测工具

网易开源的Emmagee:主要用于监控单个App的CPU,内存,流量,启动耗时,电量,电流等性能状态的变化,且用户可自定义配置监控的频率以及性能的实时显示,并最终生成一份性能统计文件。

ListView的优化

1、convertView复用
2、ViewHolder内部类
3、分页加载
4、监听AbsListView接口,滑动时停止网络加载图片,滑动停止时才进行网络加载
5、LRUCache图片缓存,第一次网络加载后把图片缓存到内存中,避免重复请求网络拉取数据
6、Bitmap图片压缩,对原始图片进行缩放,防止因图片过大占用太多系统内存
7、使用线程池加载图片,如果采用普通线程的话,当ListView滑动时可能会产生大量的线程
8、开启硬件加速UI渲染,解决UI卡顿的问题


参考

《Android开发进阶:从小工到专家》 第6章 性能优化

《App架构师》第9章 App性能优化系列

推荐阅读

Android性能优化:那些不可忽略的绘制优化

性能优化——布局优化

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容