- 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. 传输数据格式选择
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
SparseArray
、SparseBooleanArray
、SparseIntArray
。api
III. 数据库相关
建多索引的原则: 哪一个字段能够最快的减小查询结果,就把该字段放在最前面数组
没法使用索引的状况
- 操做符
BETWEEN
、LIKE
、OR
- 表达式
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#options
的InNativeAlloc
参数为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的
shrinkResources
与minifyEnabled
参数能够简单快速的在编包的时候自动删除无用资源
- 因为resources.arsc在api8之后,aapt中默认采用UTF-8编码,致使资源中大都是中文的resources.arsc相比采用UTF-16编码更大,此时,能够考虑aapt中指定使用UTF-16
- 谷歌建议,大于10M的大型应用考虑安装到SD卡上: App Install Location
- 固然运维也是一方面: Optimize Your App
- 在已知而且不须要栈数据的状况下,就没有必要须要使用异常,或建立
Throwable
生成栈快照是一项耗时的工做。