为了账号安全,请及时绑定邮箱和手机立即绑定

Android性能调优・技术优化点集合

标签:
Android

最近一个星期居然没有产品的需求,本来打算涂几个妹子过双 11,突然想到许多新人进项目组后会把项目以前踩的坑给再次踩一边,特别是一些会引发性能问题的 “有坏味道” 的代码,虽然一点有问题的代码暂时不管也不会有多大的影响,但是 “千里之堤,毁于蚁穴”,一旦问题严重了就不好处理了。不能指望每次都做好完整的 Code Review,最好的做法是把“性能优化” 的技术点总结一下,输出一个文档,给那些新加入的小伙伴们看看,免得重复踩坑。

其实性能调优涉及到多方面的工作,一晚上也只能想到这么多,而且都是一些老生常谈、炒冷饭的东西,这个贴的目的在于想骗一些高质量的干货(我从未见过如此厚颜无耻之人 + 脑补诸葛孔明表情图),然后我再整合进来,接下来再把每一点都讲详细一点,配合项目中遇到的实例案例进行分析,最好再写个 DEMO 之类的放到 Github 骗骗粉之类的。

请大家补充要点啊,我一并处理。以下只是一时想到写的笔记,详细的分析还需要一点时间。

要点

使用异步

  • 保持 APP 的高度响应,不要在 UI 线程做耗时操作,多使用异步任务

  • 使用线程时要做好线程控制;使用队列、线程池

  • 谨慎使用糟糕的 AysncTask、Timer

  • 警惕异步任务引起的内存泄露

  • 应该异步任务分类,比如 HTTP,图片下载,文件读写,每一类的异步任务维护一个任务队列,而不是每一个任务都开一个线程(Volley 表示我一个可以搞定这些全部 (:з」∠))

  • 这些常用的任务应该做好优先级处理(一般 JSON 数据优先于图片等静态数据的请求)

  • 一般异步任务应该开启一个 SingleAsyncTask,保证一时只有一个线程在工作

  • HTTP 和图片下载尽量使用同一套网络请求

  • 使用 MVP 模式规范大型 Activity 类的行为,避免异步任务造成的内存泄露

避免内存泄露

  • 了解虚拟机内存回收机制

  • 频繁 GC 也会造成卡顿,避免不必要的内存开销

  • 错误的引用姿势造成的内存泄露(啊~ 要泄了~)

  • 常见的 Activity 泄露(单例、Application、后台线程、无限动画、静态引用)

  • Bitmap 泄露(HoneyComb 这个问题之前压力好大)

  • 尽量使用 IntentService 代替 Service,前者会自动 StopItself

  • 排查内存泄露问题的方法(我一直以来都是简单暴力的人肉 dump 检查大法)

  • 使用 LeakCanary 自动检查 Activity 泄露问题

  • 对内存负载要保持敏感(Sharp)

视图优化

  • 布局优化、减少层次,Include Merge

  • 使用 ViewStub 避免不必要的 LayoutInflate,使用 GONE 代替重复 LayoutInflate 同一个布局

  • 避免过度绘制,应该减少不必要的布局背景;布局层次太深会造成过度绘制以及 Measure、Layout 等方法时间复杂度的指数增长

  • 使用过渡动画,比如给图片的呈现加一个轻量的淡入效果会让视觉上变得流畅许多

  • 避免过度的动画,不要让一个界面同时出现多出动画,比如 List 滚动时 Item 项要停止播放动画或者 GIF

  • 复杂动画使用 SurfaceView 或 TextureView

  • 尽量提供多套分辨率的图片,使用矢量图

Adapter 优化

  • 复用 convertView,用 ViewHolder 代替频繁 findViewById

  • 不要重复 setListener,要使用 v.getId 来复用 Listener,不然会创建一堆 Listener 导致频繁 GC

  • 多布局要采用 MultiItemView,而不是使用一个大布局然后动态控制需要现实的部分

  • 不要在 getView 方法做做耗时的操作

  • 快速滚动列表的时候,可以停止加载列表项的图片,停止列表项的动画,不要在这时候改变列表项的布局

  • 尽量用 RecyclerView(增量 Notify 和 RecycledViewPool 带你飞)

代码优化

  • 算法优化,减少时间复杂度,参考一些经典的优化算法

  • 尽量使用 int,而不是 float 或者 double

  • 尽量采用基本类型,避免无必要的自动装箱和拆箱,浪费时间和空间

  • 选用合适的集合类(尽量以空间换时间)、选用 Android 家的 SparseArray,SparseBooleanArray 和 LongSparseArray

  • 避免创建额外的对象(StringBuilder)

  • 使用 SO 库完成一些比较独立的功能(高斯模糊)

  • 预处理(提前操作)一些比较耗时的初始化工作统一放到启动图处理

  • 懒加载(延迟处理)规避 Activity 的敏感生命周期

  • Log 工具类,要在编译时删掉调试代码,而不是在运行时通过判断条件规避

  • 优先使用静态方法、公有方法还是私有方法?速度区别很大哦

  • 类内部直接对成员变量进行操作,不要使用 getter/setter 方法,调用方法耗额外的时间

  • 给内部类访问的外部类成员变量要声明称包内可访问,而不是私有,不然编译的时候还是会自动创建用于访问外部类成员变量的方法

  • 遍历集合时,使用 i++ 代替 Iterator,后者需要额外的对象操作,应在循环体内避免这种情况

  • 如果一个基本类型或者 String 的值不会改变,尽量用 final static,编译时会直接用变量的值替换变量,也就不需要在查询变量的值了

其他优化

  • 数据库优化:使用索引、使用异步线程

  • 网络优化 …… 一堆优秀的轮子

  • 避免过度使用依赖注入框架,大量的反射

  • 不过过度设计 / 抽象,多态看起来很有设计感,代价就是额外的代码、空间、时间

  • 尽量不要开启多进程,进程的开销很大

APK 瘦身

  • 开启混淆

  • 使用 zipalign 工具优化 APK

  • 适当有损图片压缩、使用矢量图

  • 删除项目中冗余的资源,之前写过一些删除没有 res 资源的脚本

  • 动态加载模块化,项目拆分啊!

性能问题的排查方法

  • GPU 条形图,没事开来看看淘宝

  • 过度绘制颜色,嗯,不要一片姨妈红就好

  • LeakCanary,自动检测 Activity 泄露,挺好用的

  • TraceView(Device Monitor),Systrace,分析哪些代码占用的 CPU 时间太大,屡试不爽

  • Lint,检查不合理的 res 资源

  • layoutopt(还是 optlayout?),对当前布局提出优化建议,已被 lint 替代,但是还能用

  • HierarchyViewer,查看手机当前界面的布局层次,布局优化时常用(只用于模拟器,真机上用要 ROOT,不想 ROOT 加得使用 ViewServer)

  • StrictMode,UI 操作、网络操作等容易出现性能问题的地方,如果出现异常情况 StrictMode 会报警

原文链接:http://www.apkbus.com/blog-705730-61723.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消