收集一下Android应用性能调优的技术点

信息

作者:Kaede
链接:https://github.com/kaedea

神马情况

最近一个星期居然没有产品的需求,本来打算涂几个妹子过双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
  • 多布局要采用MutilItemView,而不是使用一个大布局然后动态控制需要现实的部分
  • 不要在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会报警

欢迎各位补充

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,815评论 25 707
  • java 接口的意义-百度 规范、扩展、回调 抽象类的意义-乐视 为其子类提供一个公共的类型封装子类中得重复内容定...
    交流电1582阅读 2,215评论 0 11
  • 我回忆到这里,一堆问题在我的脑子里像细菌繁殖一样迅速产生:为什么那时候竟然没有想到过父母?为什么那时候没有对陌生的...
    怒隶阅读 219评论 0 1
  • 001互联网时代的三变化 ①信息传播加速且影响范围巨大; ②信息不对等变成信息对等; ③互联网的信息传播是中心化传...
    Aream阅读 113评论 0 1
  • 沿着狭长的海岸线,我一直在找一个有沙的海滩。最后却找到一个建在高地上的泳池。 刚进入泳池后水还比较浅,后来水涨得越...
    蓝矿阅读 137评论 1 1