Android性能:读写篇

本文探讨了Android应用中读写操作的性能优化,包括避免主线程读写,减少冗余读/写,以及提高读写效率。建议在子线程执行I/O操作,使用缓存和apply方法,优化数据库操作,使用高效IO流类,并合理设置缓冲区大小,以提升应用性能。

所谓读写操作(也叫IO操作):通过将外部存储的文件,读取到内存(RAM)中进行修改处理,或是将内存中的数据写入文件存储到外部存储(ROM或者SD卡);

由于硬件的限制,相比于内存数据,磁盘数据的读写明显要慢得多,可能会让平时时间很短的操作被放大几十倍,特别是Rom跟SD对于I/O需要频繁操作的,关于读写的性能要特别注意,除了已知的文件读写之外,SharePreferences与数据库的相关操作本质上也是文件读写,同样需要注意,关于读写操作的性能问题,可能有以下几个方面进行优化。

一、避免主线程读写

由于读写操作时间长,如果在UI线程执行,会堵塞UI,甚至可能导致ANR,因此 I/O 操作要在子线程中进行(包括SharedPreference与SQLite本质上也是文件读写)。

SharedPreference初始化是在主线程的,因此要提前初始化。

使用SharedPreference的apply替代commit方法,apply是异步操作,commit是同步操作。

二、减少冗余读/写

冗余读写指同一个文件在应用运行期间被多次读取或者写入,这会消耗不必要的时间;可从以下几个方面进行优化:

  • 缓存

需要在多个地方多次读取同一文件时(如配置文件),只读一次,把需要的内容写到缓存中

  • 延迟写入

SharedPreference 每调用一次commit就会执行一次写入操作,只需要保留最好的一个commit方法即可;更好的是用apply替代commit,commit是同步操作,apply是异步操作。

  • 减少操作

减少重复打开数据库,缓存数据库连接,数据库在打开后,先不要关闭,在应用程序退出时再关闭。

批量更新数据库,避免多次进行数据库读写。

优化sql语句减少无谓的查询(如 数据库中写入一条数据,若这条数据不存在,插入数据,若已存在,修改这条数据,这种情况下使用"insert or replace" 语句来避免先查询,后操作)。

SQLite数据库设置主键时慎用AUTOINCREMENT,因为使用AUTOINCREMENT会增加磁盘读写次数,使得INSERT耗时会大大增加。

三、提高读写效率

  • 调用高效IO流Java类:

文件读写时使用ByteArrayOutputStream、BufferedOutputStream或ByteArrayInputStream、BufferedInputStream进行缓存。

ObjectOutputStream跟ObjectInputStream 在读写对象时,每个数据成员会带来一次 I/O 操作,即使很小的文件也会有成千上万次I/O的,还有FileInputStream跟FileOutputStream,也有冗余读写操作;如果在上面再封装一个输出流ByteArrayOutputStream、BufferedOutputStream或ByteArrayInputStream、BufferedInputStream,这两类会将数据存到缓存区中,然后再一次性进行读写,可大大减少磁盘IO。

  • 合理设置Buffer大小

文件读取时,有时会用到byte[]进行缓存,但是不同的文件大小需要设置的大小不同,设置太小会引起读写操作太多次,但是Buffer也不是越大越好,如果太大会导致申请Buffer的时间变长;

有两个准则:一是Buffer size不能大于 文件大小;二是Buffer size 根据文件保存所挂载的目录的block size来确认Buffer大小,而数据库的pagesize,就是这样确定的(具体可见Android源码中SQLiteGlobal.java的getDefaultPageSize())。

  • Bitmap进行decode时使用高效方法

BitmapFactory.java提供多个decode Bitmap的API,有decodeFile()、 decodeResource()、 decodeByteArray()、 decodeFileDescriptor()、 decodeStream()、 decodeResourceStream()。decodeFile方法在安卓4.4以后使用的是FileInputStream,FileInputStream是字节流,读磁盘次数多,耗时长,不建议使用;而decodeStream使用BufferedInputStream读资源比FileInputStream读取资源的效率高,且FileInputStream对象的read方法会出现阻塞。

因此解码Bitmap建议使用decodeStream(),来代替decodeFile(),同理使用decodeResourceStream替代decodeResource。

 

注:本文主要在阅读了《Android性能实战》中并根据其第一章关于磁盘的优化部分归纳总结后进行撰写。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值