所谓读写操作(也叫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性能实战》中并根据其第一章关于磁盘的优化部分归纳总结后进行撰写。
本文探讨了Android应用中读写操作的性能优化,包括避免主线程读写,减少冗余读/写,以及提高读写效率。建议在子线程执行I/O操作,使用缓存和apply方法,优化数据库操作,使用高效IO流类,并合理设置缓冲区大小,以提升应用性能。
818

被折叠的 条评论
为什么被折叠?



