当前位置: 首页 > news >正文

SharedPreferences

Android轻量级数据存储

import android.content.Context;
import android.content.SharedPreferences;public class SharedPreferencesUtil {private SharedPreferences sharedPreferences;private SharedPreferences.Editor editor;public SharedPreferencesUtil(Context context, String fileName) {this.sharedPreferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);this.editor = sharedPreferences.edit();}public void putString(String key, String value) {editor.putString(key, value);editor.apply(); //异步提交}public String getString(String key, String defaultValue) {return sharedPreferences.getString(key, defaultValue);}public void putInt(String key, int value) {editor.putInt(key, value);editor.apply();}public int getInt(String key, int defaultValue) {return sharedPreferences.getInt(key, defaultValue);}public void putBoolean(String key, boolean value) {editor.putBoolean(key, value);editor.apply();}public boolean getBoolean(String key, boolean defaultValue) {return sharedPreferences.getBoolean(key, defaultValue);}public void remove(String key) {editor.remove(key);editor.apply();}public void clear() {editor.clear();editor.apply();}
}

一个键值对保存的xml文件,存储在data/data/package/shared_prefs文件夹下

获取Sp的源码:

public SharedPreferences getSharedPreferences(String name, int mode) {if (mPackageInfo.getApplicationInfo().targetSdkVersion <Build.VERSION_CODES.KITKAT) {if (name == null) {name = "null";}}File file;synchronized (ContextImpl.class) {if (mSharedPrefsPaths == null) {mSharedPrefsPaths = new ArrayMap<>();}file = mSharedPrefsPaths.get(name);if (file == null) {file = getSharedPreferencesPath(name);mSharedPrefsPaths.put(name, file);}}return getSharedPreferences(file, mode);
}@Override
public SharedPreferences getSharedPreferences(File file, int mode) {SharedPreferencesImpl sp;synchronized (ContextImpl.class) {final ArrayMap<File, SharedPreferencesImpl> cache =getSharedPreferencesCacheLocked();sp = cache.get(file);if (sp == null) {checkMode(mode);sp = new SharedPreferencesImpl(file, mode);cache.put(file, sp);return sp;}}if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {sp.startReloadIfChangedUnexpectedly();}return sp;
}

SharedPreferences是个接口,其实现类是SharedPreferencesImpl,其构造方法如下:

SharedPreferencesImpl(File file, int mode) {mFile = file;mBackupFile = makeBackupFile(file);mMode = mode;mLoaded = false;mMap = null;mThrowable = null;startLoadFromDisk();
}

在startLoadFromDisk()中会从磁盘中加载xml文件,并将内容映射到mMap中
每次获取Sp对象时,都会把所有的存储数据从磁盘读取到内存,所以如果存储内容过多,会导致OOM

public String getString(String key, @Nullable String defValue) {synchronized (mLock) {awaitLoadedLocked();String v = (String)mMap.get(key);return v != null ? v : defValue;}}

从上面的代码可以看出,在调用getString()的时候加锁了,如果在主线程调用,意味着主线程被锁,如果此时Sp对象还未被获取,那么只有等Sp对象获取之后才能释放锁,这里可能会造成阻塞

public boolean commit() {long startTime = 0;MemoryCommitResult mcr = commitToMemory();SharedPreferencesImpl.this.enqueueDiskWrite(mcr, null /* 在当前线程同步写入 */);try {mcr.writtenToDiskLatch.await();} catch (InterruptedException e) {return false;} notifyListeners(mcr);return mcr.writeToDiskResult;
}

从上面代码可以看出commit()调用时,将内存中的Sp写入到磁盘,是个耗时操作,所以不要频繁的调用commit(),频繁的调用可能会导致ANR

public void apply() {final long startTime = System.currentTimeMillis();final MemoryCommitResult mcr = commitToMemory();final Runnable awaitCommit = new Runnable() {@Overridepublic void run() {try {mcr.writtenToDiskLatch.await();} catch (InterruptedException ignored) {}}};QueuedWork.addFinisher(awaitCommit);Runnable postWriteRunnable = new Runnable() {@Overridepublic void run() {awaitCommit.run();QueuedWork.removeFinisher(awaitCommit);}};SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);notifyListeners(mcr);}

从上面的源码可以看出每次apply都会创建一个任务添加到 QueueWork中,如果频繁的执行写入操作,会造成ANR,
Android8.0之后优化,如果连续多次写入,只执行最后一次

Sp通过锁来保证线程安全,没有进程安全

文件备份机制
Sp在写入内容打磁盘时,会把原来的内容备份,写入成功后,会删掉备份内容
如果写入时发生异常,那么在下次启动时,如果有备份文件,会把备份文件作为源文件,未成功的文件删掉

http://www.lryc.cn/news/68769.html

相关文章:

  • 服务(第二十五篇)redis的优化和持久化
  • David Silver Lecture 7: Policy Gradient
  • 知识图谱学习笔记——(五)知识图谱推理
  • 用vs2010编译和调试多个arx版本的arx项目
  • 安全相关词汇
  • 最新入河排污口设置论证、水质影响预测与模拟、污水处理工艺分析及典型建设项目入河排污口方案报告书
  • 2023年认证杯二阶段C题数据合并python以及matlab多途径实现代码
  • Win11校园网不弹出登录页面怎么回事?
  • S32K144低功耗休眠与唤醒实践总结
  • 一文吃透 Vue 框架教程(上)
  • 堆排序与取topK java实现
  • https通信流程通俗理解
  • 银行零售业务转型方法论:打造数字化的“有机体”
  • 【STM32】STM32使用RFID读卡器
  • spring集成mybatis的原理
  • 限速神器RateLimiter源码解析 | 京东云技术团队
  • spring中怎样优化第三方bean?
  • 8分钟的面试,我直呼太变态了......
  • 别去外包,干了3年,彻底废了......
  • ipa如何安装到iphone
  • 照片从安卓手机中消失了?让他们恢复回来的几个方法请收好
  • 哪个年龄段人群喜欢养宠物?18-25岁占比最高,达31%
  • 使用Apache POI数据导出及EasyExcel进行十万、百万的数据导出
  • 八种故障排障思路
  • JavaScript全解析——this指向
  • MySQL中ON DUPLICATE KEY UPDATE和REPLACE INTO区别
  • 37本国产SCI期刊推荐!涵盖9大领域,建议收藏!②
  • 掌握无缝云迁移方法的数据集成
  • unity 3种办法实现血条效果并实现3d世界血条一直看向摄像机
  • Jenkins流水线整合k8s实现代码自动集成和部署