一、磁盘
1.如果需要频繁读某个文件,请做缓存操作。
2.SharePreferences的commit对应一次文件的打开与关闭。
另外,apply是异步操作,commit为同步操作。
3.主线程I/O与子线程I/O之争。
- 若I/O操作放在主线程,将会影响UI的绘制。
- 若I/O操作放在子线程,虽然不影响UI线程,但由于子线程优先级不高,I/O耗时会变长。
4.对象序列化最佳实践。
- 序列化写:BufferedOutputStream/ByteArrayOutputStream + ObjectOutputStream
- 序列化读:BufferedInputStream/ByteArrayInputStream + ObjectInputStream
- 原理:ObjectOutputStream在序列化的时候,会把内存中的每个对象保存到磁盘中,在保存对象时,每个数据成员都会带来一次I/O操作。使用缓冲区,可有效减少磁盘I/O次数。比如3K的大对象,使用2K的缓冲区,两次I/O即可。
5.使用Buffer太小或太小,也会影响I/O效率。
- 在读写时候使用缓冲区可以减少读写次数,从而减少了切换内核态的次数,提高读写效率。
- Buffer也不是越大越好,因为Buffer过大,申请时间会变长。
- 经验值8KB = 8192byte。
6.解压文件的最佳实践。
结论:
- 如果Zip文件已在磁盘(已下载),且解压所有Zip中所有文件,建议使用ZipFile,效率较ZipInputStream提升15%-27%。
- 仅解压Zip某些文件,建议使用ZipFile,因为ZipFile有RandomAccessFile特性。
- 如果Zip不在磁盘上,或顺序解压一小部分文件,或Zip文件目录遭到损害,建议使用ZipInputStream。
最佳实践代码:
|
|
7.请勿重复打开数据库。
由SQLiteDatabase的#getWriteableDatabase()方法的注释:一旦打开数据库,该链接会被缓存,以供下一次使用,只有当真正不需要时,调用close()关闭。
8.减少使用select *。
9.请勿滥用AUTOINCREMENT关键字。
AUTOINCREMENT用于数据库主键唯一性、递增性,会增加CPU、内存、磁盘空间和磁盘I/O的负担,所以尽量不要用。因为AUTOINCREMENT实现原理是维护另一张表,表记录了已使用的最大行号等信息。
二、内存
获取虚拟机分配的内存大小:
|
|
那么什么是管理好内存呢?
- 减少内存的申请回收。
- 减少常驻内存。
- 避免内存泄漏。
实用工具:
- LeakCanary
- LeakInspector
- Android Allocation Tracer
1.内类是危险的编码方式
java的非静态类对象会持有外部类的强引用。在Android中,某些类是具有特殊的生命周期的,比如Context、Fragment。一旦他们与非静态类对象生命周期不同步,就会出现内存泄漏问题,甚至是crash。
解决方案:
- 尽量不用非静态内部类。
- 若需要外部类引用,请使用弱引用。
|
|
2.适当选择图片解码方式
头像、缩略图等小图,如果没必要高清显示,那么可以选择RGB_565。
- RGB_565 每个像素使用2字节16位保存颜色信息,其中红色5位,绿色6位,蓝色5位。
- Android默认使用ARGB_8888,包含透明通道,共4字节32位。
3.大图裁剪压缩
大图解码往往是OOM的元凶。
4.提高Bitmap的缓存命中率
比如社交类产品一般有默认头像,url一般均为同一个,在做图片缓存时,应使用url作为key。
三、网络
1.业务成功率
- 弱网
- 网络拥塞
2.业务网络延时
- DNS解析
- 长连接
- 短连接
- 接收窗口
3.业务带宽成本
- 图片、大数据压缩
- 数据增量,比如好友列表应采用增量更新,需要制定协议
- 资源去重,主要是压缩包和非压缩包之间去重
4.总结
- 避免重复上传下载
- JS/CSS/HTML需要压缩
- 图片压缩
- 定时网络请求尽量合并在一个时间
- 网络重试必须有明显结束条件
- 流量兜底能力,避免流量偷跑,服务端控制终止数据传输。
四、CPU
1.争夺CPU资源
- 计算密集型
- I/O密集型
2.建议
- 能用int不要用float
- 容器类选择合适的,比如ArrayMap,SparseArray,ConcurrentHashMap
- 容器类如果可以,请构建的时候设置它的容量,避免不必要的扩容
- 根据CPU核心数选择合适线程数
- 优化算法
五、电量
针对CPU唤醒优化。
- 锁屏,灭屏,后台停止耗电操作:动画、SurfaceView绘制。
- 锁屏,灭屏正确释放WakeLock,否则导致CPU无法休眠。