Android开发优化宝典

I. 网络相关

  • http头信息带Cache-Control域 肯定缓存过时时间 防止重复请求
  • 直接用IP直连,不用域名,策略性跟新本地IP列表。 – DNS解析过程耗时在百毫秒左右,而且还有可能存在DNS劫持。
  • 图片、JS、CSS等静态资源,采用CDN(固然若是是使用7牛之类的服务就已经给你搭建布置好了)
  • 全局图片处理采用漏斗模型全局管控,所请求的图片大小最好依照业务大小提供/最大不超过屏幕分辨率须要,若是请求原图,也不要超过GL10.GL_MAX_TEXTURE_SIZE
  • 全局缩略图直接采用webp,在尽量不损失图片质量的前提下,图片大小与png比缩小30% ~ 70%
  • 若是列表里的缩略图服务器处理好的小图,能够考虑直接在列表数据请求中,直接以base64在列表数据中直接带上图片(国内还比较少,海外有些这种作法,好像web端比较常见)
  • 轮询或者socket心跳采用系统AlarmManager提供的闹钟服务来作,保证在系统休眠的时候cpu能够获得休眠,在须要唤醒时能够唤醒(持有cpu唤醒锁)
  • 能够经过将零散的网路的请求打包进行一次操做,避免过多的无线信号引发电量消耗。

1. 传输数据格式选择

  • 若是是基本须要全量数据的,考虑使用Protobuffers (序列化反序列化性能高于json)
  • 若是传输回来的数据不须要全量读取,考虑使用Flatbuffers (序列化反序列化几乎不耗时,耗时是在读取对象时(就这一部分若是须要优化,能够参看Flatbuffer Use Optimize

2. 输入流

使用具备缓存策略的输入流html

建议替换为
InputStream BufferedInputStream
Reader BufferedReader

II. 数据结构

若是已知大概须要多大,就直接给初始大小,减小扩容时额外开销。android

1. List

ArrayList

里面就一数组,内存小,有序取值快,扩容效率低git

LinkedList

里面就一双向链表,内存大,随机插入删除快,扩容效率高。github

2. Hash

HashSet

里面就一个HashMap,用key对外存储,目的就是不容许重复元素。web

ConcurrentHashMap

线程安全,采用细分锁,锁颗粒更小,并发性能更优数据库

Collections.synchronizedMap

线程安全,采用当前对象做为锁,颗粒较大,并发性能较差。编程

3. Int做为Key的Map

针对该特性进行了优化,采用二分法查找,简单数组存储。json

SparseArraySparseBooleanArraySparseIntArrayapi

III. 数据库相关

建多索引的原则: 哪一个字段能够最快的减小查询结果,就把该字段放在最前面数组

没法使用索引的状况

  • 操做符BETWEENLIKEOR
  • 表达式
  • CASE WHEN

不推荐

  • 不要设计出索引是其余索引的前缀(没有意义)
  • 更新时拒绝直接全量更新,要更新哪列就put哪列的数据
  • 若是最频繁的是更新与插入,别建不少索引 (本来表就很小就也不必建)
  • 拒绝用大字符串建立索引
  • 避免建太多索引,查询时可能就不会选择最好的来执行

推荐

  • 多使用整型索引,效率远高于字符串索引
  • 搜索时使用SQL参数("?", parameter)代替字符串拼接(底层有特殊优化与缓存)
  • 查询须要多少就limit多少(如判断是否含有啥,就limit 1就好了嘛)
  • 若是出现很宽的列(如blob类型),考虑放在单独表中(在查询或者更新其余列数据时防止没必要要的大数据i/o影响性能)

IV. JNI抉择

Android JVM相关知识,可参看: ART、Dalvik

Android JNI、NDK相关知识,可参看: NDK

JNI不必定显得更快,有些会更慢。

特色: 不用在虚拟机的框子下写代码

  • 能够调用更底层的高性能的代码库 – Good
  • 若是是Dalvik,将省去了由JIT编译期转为本地代码的这个步骤。 – Good
  • Java调用JNI的耗时较Java调用Java确定更慢,虽然随着JDK版本的升级,差距已经愈来愈小(JDK1.6版本是5倍Java调用Java方法的耗时) – Bad
  • 内存不在Java Heap,没有OOM风险,有效减小gc。 – Good

一些重要的参数之类,也能够考虑放在Native层,保证安全性。参考: Android应用程序通用自动脱壳方法研究

V. 多进程抉择

360 17个进程: 360手机卫士 Android开发 InfoQ视频 总结

  • 充分独立,解耦部分
  • 大内存(如临时展现大量图片的Activity)、没法解决的crash、内存泄漏等问题,考虑经过独立进程解决
  • 独立于UI进程,须要在后台长期存活的服务(参看Android中线程、进程与组件的关系)
  • 非己方第三方库(没法保证稳定、性能等问题,而且独立组件),可考虑独立进程

最后,多进程存在的两个问题: 1. 因为进程间通信或者首次调起进程的消耗等,带来的cpu、i/o等的资源竞争。2. 也许对于部分同事来讲,会还有可读性问题吧,毕竟多了层IPC绕了点。

VI. UI层面

相关深刻优化,可参看Android绘制布局相关

对于卡顿相关排查推荐参看: Android性能优化案例研究(上)Android性能优化案例研究(下)

  • 减小没必要要的不透明背景相互覆盖,减小重绘,由于GPU不得不一遍又一遍的画这些图层
  • 保证UI线程一次完整的绘制(measure、layout、draw)不超过16ms(60Hz),不然就会出现掉帧,卡顿的现象
  • 在UI线程中频繁的调度中,尽可能少的对象建立,减小gc等。
  • 分步加载(减小任务颗粒)、预加载、异步加载(区别出耗时任务,采用异步加载)

VII. 库推荐

能够参考Falcon Pro做者的推荐: Falcon Pro 3如何完成独立开发演讲分析

1. 代码编写习惯

RxJava (响应式编程,代码更加简洁,异步处理更快快捷、异常处理更加完全、数据管道理念)

相关了解能够参看: RxJava

2. 图片加载:

3. 网络底层库:

Okhttp: 默认gzip、缓存、安全等

4. 网络基层:

Retrofit: 很是好用的REST Client,结合RxJava简单API实现、类型安全,简单快捷

5. 数据库层:

Realm: 效率极高(Falcon Pro 3的做者Joaquim用了该库之后,全部数据库操做都放到了UI线程)(基于TightDB,底层C++闭源,Java层开源,简单使用,性能远高于SQLite等)

6. Crash上报:

Fabric: 全面的信息(新版本还支持JNI Crash获取和上报)、稳定的数据、及时的通知、强大的反混淆(其实在混淆后有上传mapping)

7. 内存泄漏自动化检测

LeakCanary: 自动化泄漏检测与分析 ( 能够看看这个LeakCanary使用总结Leakcanary Square的一款Android/Java内存泄漏检测工具)

8. 其余

VIII. 内存泄漏相关

  • 没法解决的泄漏(如系统底层引发的)移至独立进程(如2.x机器存在webview的内存泄漏)
  • 大图片资源/全屏图片资源,要不放在assets下,要不放在nodpi下,要不都带,不然缩放会带来额外耗时与内存问题
  • 4.x在AndroidManifest中配置largeHeap=true,通常dvm heep最大值可增大50%以上。
  • Activity#onDestory之后,遍历全部View,干掉全部View可能的引用(一般泄漏一个Activity,连带泄漏其上的View,而后就泄漏了大于全屏图片的内存)。
  • 万金油: 静态化内部类,使用WeakReference引用外部类,防止内部类长期存在,泄漏了外部类的问题。

图片Decode

  • 全局统一BitmapFactory#decode出口,捕获此处decode oom,控制长宽(小于屏幕分辨率大小 )
  • 若是采用RGB_8888 oom了,尝试RGB_565(相比内存小一半以上(wh2(bytes)))
  • 若是还考虑2.x机器的话,设置BitmapFactory#optionsInNativeAlloc参数为true,此时decode的内存不会上报到dvm中,便不会oom。

IX. 编译与发布

  • 考虑采用DexGuard,或ProGuard结合相关资源混淆来提升安全与包大小,参考: DexGuard、Proguard、Multi-dex
  • 结合Gradle、Gitlab-CI 与Slack(Incoming WebHooks),快速实现,打相关git上打相关Tag,自动编相关包通知Slack。
  • 结合Gitlab-CI与Slack(Incoming WebHooks),快速实现,全部的push,Slack快速获知。
  • 结合Gradle中Android提供的productFlavors参数,定义不一样的variations,快速批量打渠道包

X. 其余

  • final能用就用(高效: 编译器在调用final方法时,会转入内嵌机制)
  • 懒预加载,如简单的ListView、RecyclerView等滑动列表控件,停留在当前页面的时候,能够考虑直接预加载下个页面所需图片
  • 智能预加载,经过权重等方式结合业务层面,分析出哪些更有可能被用户浏览使用,而后再在某个可能的时刻进行预加载。如,进入朋友圈以前经过用户行为,智能预加载部分原图。
  • 作好有损体验的准备,在一些没法避免的问题面前作好有损体验(如,非UI进程crash,能够本身解决就不要让用户感知,或者UI进程crash了,作好场景恢复)
  • 作好各项有效监控:crash(注意还有JNI的)、anr(按期扫描文件)、掉帧(绘制监控、activity生命周期监控等)、异常状态监控(本地Log根据须要不一样级别打Log并选择性上报监控)等
  • 文件存储推荐放在/sdcard/Android/data/[package name]/里(在应用卸载时,会随即删除)(Context#getExternalFilesDir()),而非/sdcard/根目录建文件夹(节操问题)
  • 经过gradle的shrinkResourcesminifyEnabled参数能够简单快速的在编包的时候自动删除无用资源
  • 因为resources.arsc在api8之后,aapt中默认采用UTF-8编码,致使资源中大都是中文的resources.arsc相比采用UTF-16编码更大,此时,能够考虑aapt中指定使用UTF-16
  • 谷歌建议,大于10M的大型应用考虑安装到SD卡上: App Install Location
  • 固然运维也是一方面: Optimize Your App
  • 在已知而且不须要栈数据的状况下,就没有必要须要使用异常,或建立Throwable生成栈快照是一项耗时的工做。
相关文章
相关标签/搜索