Android存储优化

关于存储的操作,一切的核心优化都在以下三个方面:

1.避免在主线程I/O

2.减少I/O读写量

3.减少I/O的操作次数

从这三个方面,下面介绍如何针对不同的存储方式进行相应的优化:

  • 针对SharedPreferences,需要做到如下的优化:

    • SP文件没有被加载到内存时,调用getSharedPreferences方法会初始化文件并读入内存,建议在Application中初始化,重写attachBaseContext方法,SharedPreference的context传入Application对象即可,最好使用单例,不必每次都获取Sp对象,减少开销。(可以归结到预加载,后续使用时,效率更高)
    • 不要使用SharedPreference存储大文件及存储大量的key和value,这样的话会造成界面卡顿或者ANR,比较占内存。记住它是简单存储,如果有类似的需求请考虑数据库、磁盘文件存储等等。(这样做的目的就是减少I/O的读写量)
    • 推荐使用apply进行存储,这也是官方推荐,当读入内存后,因为它是异步写入磁盘的,所以效率上会比commit好,如果你需要存储状态或者即存即用的话还是尽量使用commit。 (这样做的本质其实就是尽量避免在主线程操作I/O)
    • 尽量不要存放Json及html,数据少可以,无需担心,大量的话请放弃。(这个其实也是说的是减少I/O的读写量)
    • 不要所有的数据都存在一个文件,不同类型的文件或者数据可以分开多个文件存储, 避免使用一个大文件,这样可提高读取速度。(这个其实也是说的是减少I/O的读写量)
    • 跨进程操作不要使用MULTI_PROCESS标志,而是使用contentprovide等进程间通信的方式。(跨进程使用sp,官方文档提示不支持多进程,多进程使用数据可能会丢失。不建议使用)
    • 如果你的项目对于存储性能要求非常高的情况,可以考虑放弃系统的SharedPreference存储,推荐你使用腾讯的高性能组件MMKV
  • 针对Sqlite数据库,需要做到如下的优化:

    • 减少使用select * ,这样就能减少从数据库读取的数据量,减少耗时。(本质就是减少I/O读写量)
    • 利用缓存减少重复的读取。(本质就是减少I/O读写量)
    • 数据库减少AUTOINCREMENT 因为这样要多操作一个表,InSert耗时2~4倍。(本质就是减少I/O读写量)
    • 使用合适的数据库分页,sqlite读/写磁盘是以page为单位的,在3.12.0版本之前,Sql默认page size是1KB,从3.12.0开始,page size调整为4KB。(本质就是减少I/O读写量)
    • 频繁查询的表使用索引,索引可以极大地减少读磁盘的数据量,极大的提升效率,但是会增加插入和更新的时间,所以,对于读取频率大于写入频率的情景,建议使用。(本质就是减少I/O读写量)
    • 避免无效索引,无效索引的问题通常是严重的。除了触发全表扫描,产生大量冗余的读/写之外,还降低了写入性能。(本质就是减少I/O读写量)
    • 批量更新数据库使用事务,启用事务,根据业务规模,会大量减少I/O读/写量和操作次数,从而提升效率.(本质是减少I/O次数)
    • ZIP压缩大量小文件时建议使用ZipInputStream。
    • 增加查询条件当你只要一条数据时增加limit 1,这样搜索到了后面的就不会再查询了,大大的加快了速度。(本质就是减少I/O读写量)
    • 提前将字段的index映射好减少getColumnIndex的时间,可以缩短一半的时间。(本质就是减少I/O读写量)
    • 通过冗余换取查询速度,这个要看具体使用场景了,如果太多冗余,也会造成增加I/O的读写量和次数。
  • 针对ContentProvider优化,需要做到如下的优化:

    • ContentProvider底层操作的是数据库。ContentProvider类里,重写applyBatch方法,加入事务
     @Override
     public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation>  operations)
             throws OperationApplicationException{
           SQLiteDatabase db = mOpenHelper.getWritableDatabase();
           db.beginTransaction();
           try{
               ContentProviderResult[]results = super.applyBatch(operations);
               db.setTransactionSuccessful();
               return results;
           }finally {
               db.endTransaction();
           }
    }
    
    在处理数据时使用ContentProviderOperation:
    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    
    然后循环加入数据库操作:
    ContentValues value = new ContentValues();
     ops.add(ContentProviderOperation.newUpdate(MyProvider.CONTENT_URI)
      .withSelection("_id='" + entry.getId() + "'", null)
      .withValues(value)
      .withYieldAllowed(true)
      .build());
    
    然后提交操作:
    try {
       mContext.getContentResolver().applyBatch(MyProvider.AUTHORITY, ops);
       } catch (RemoteException e) {
           e.printStackTrace();
       } catch (OperationApplicationException e) {
           e.printStackTrace();
       }
    }
    
    这样,用了事务之后,数据库效率会大大提升。

总结:

在这里插入图片描述
参考:

《Android移动性能实战》

提高android ContentProvider的效率

SharedPreference性能优化看这一篇就够了

android数据库优化

Android 《Android移动性能实战》学习笔记

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值