【知识整理】这可能是最好的性能优化教程(一)
本文首发于我的简书:http://www.jianshu.com/p/17fd325b28f6
前言
性能检测与分析,一直在 APP 开发中相当重要,但又被我们常常忽略。很多 APP 或者开发者总是急功近利,总想着快速充实 APP 的相关功能,把开发进度放在首位没有问题,可很多时候就没有然后了,这在整个开发界屡见不鲜。
在这样的大背景下,加之我之前写的 RxJava 2.0 系列 收到较好的反馈,诱导我想出这么一个性能优化系列。
一些你可能需要知道的
了解我的知道,我出的系列基本都是比较基础,而且侧重于常见必备。所以不一定全面,也不一定深入,所以希望理解。
性能优化大概可以概括为:
- 性能优化说起来很简单,但做起来难。
- 性能优化点多并且繁杂,需要耐心和经验。也许每个优化点很小,但积累起来会从量变变成质的飞跃。
- 性能优化必须建立在产品设计之上,不能为了追求性能而忽略了产品设计。
提供一些资源 ( 你可能需要梯子 )
善用 ArrayMap
程序内存的管理是否合理高效对应用的性能有着很大的影响,有时候对容器的使用不当也会导致内存管理效率低下。想必已经有很多童鞋知道了 SparseArray
,但它只是用于替代 List。
我们经常会在程序中用到 HashMap
,它非常好用,这毋庸置疑。但它却非常耗内存。HashMap
的工作原理这里我们就不讲了,有兴趣的自行科普。
更高效的 ArrayMap 容器
为了解决 HashMap
更占内存的弊端,Android 提供了内存效率更高的 ArrayMap
。它内部使用两个数组进行工作,其中一个数组记录 key hash 过后的顺序列表,另外一个数组按 key 的顺序记录 Key - Value 的值。如下图所示:
当你想获取某个 Value 的时候,ArrayMap
会计算输入 key 转换过后的 hash 值,然后对 hash 数组使用二分查找法寻找到对应的 index,然后我们可以通过这个 index 在另外一个数组中直接访问到需要的键值对。如果在第二个数组键值对中的 key 和前面输入的查询 key 不一致,那么就认为是发生了碰撞冲突。为了解决这个问题,我们会以该 key 为中心点,分别上下展开,逐个去对比查找,直到找到匹配的值。如下图所示:
随着数组中的对象越来越多,查找访问单个对象的花费也会跟着增长,这是在内存占用与访问时间之间做权衡交换。
既然ArrayMap中的内存占用是连续不间断的,那么它是如何处理插入与删除操作的呢?请看下图所示,演示了Array的特性:
很明显,ArrayMap
的插入与删除的效率是不够高的,但是如果数组的列表只是在一百这个数量级上,则完全不用担心这些插入与删除的效率问题。HashMap
与 ArrayMap
之间的内存占用效率对比图如下:
与 HashMap
想必,ArrayMap
在循环遍历的时候也更加简单高效,因为其采用的是 fori 循环,而 HashMap
却使用的是糟糕的 Iterator
。
并不是所有情况下都用 ArrayMap
ArrayMap
这么优秀,但并不是所有情况下都适合使用 ArrayMap
,我们应该在满足下面两个条件的时候才考虑使用 ArrayMap
:
- 对象个数的数量级最好在 1000 以内。
- 数据组织形式包含 Map 结构。
所以我们需要学会在特定清醒下选择相对更加高效的实现方式。
UI 性能确实很重要
UI 界面是整个 APP 性能的最前端展示,也是最容易看出性能问题的地方。可以毫不夸张地说,UI 性能的好坏直接影响这用户的体验和留存。UI 性能的目标是:
- 减少绘图的等待时间。
- 使帧率更加平稳、连贯。
UI 布局的核心原则
核心原则一句话,尽可能地减少 View 的数量!
我们可以通过 include
、merge
、viewstub
进行布局复用,通过控件属性 DrawableLeft、DrawableRight 等方式进行控件整合。
听说我们要尽可能地用 RelativeLayout ?
想必一些资历较老的 Android 开发者都知道,一开始系统默认创建的布局是 LinearLayout,后面替换成了 RelativeLayout,现在又变成了 ConstraintLayout 。由于我对 ConstraintLayout 不是特别了解,所以这里我着重说说 RelativeLayout 和 LinearLayout 。
我不知道在什么时候听说过,如果我们能用 RelativeLayout 的地方,尽量不要用 LinearLayout 。
这种说法是不对的,实际开发中,决不能简单地说 RelativeLayout 和 LinearLayout 谁的性能更好,必须结合实际使用来进行分析。
基本可以总结为:一般情况下,如果使用 LinearLayout,则一定要保证层级不能太深;如果使用 RelativeLayout,则需要尽量避免嵌套。
后记
以上便是本期内容,由于楼主也是开发任务很多,所以只能在有空的时候更新,如果想第一时间收到更新信息的请关注我的公众号:nanchen
作 者:
南 尘
出 处: http://www.cnblogs.com/liushilin/
关于作者:专注于移动前端的项目开发。如有问题或建议,请多多赐教!欢迎加入Android交流群:118116509
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章下部【推荐】或侧边【关注】。您的鼓励是作者坚持原创和持续写作的最大动力!
欢迎关注我的公众号,精讲面试、算法、Andrid、Java、Python,旨在打造全网最比心的公众号。