什么是SharedPreferences?
SharedPreferences是一种轻量级的数据存储方式,采用键值对的存储方式。
SharedPreferences只能存储少量数据,大量数据不能使用该方式存储,支持存储的数据类型有booleans, floats, ints, longs, and strings。
SharedPreferences存储到一个XML文件中的,路径在/data/data/<packagename>/shared_prefs/下,文件名以及存储后面详细讲述。
sharedpreferences 陪伴我们这么多年,但是目前google 推出了一个更新的更安全的方式来替代,那就是Jetpack DataStore 组件,今天我们不着重讲 DataStore ,而是来探讨一下,曾经的轻量级工具,为什么会被取代,是出了什么问题
SharedPreferences安全吗
毫无疑问,SharedPreferences是线程安全的,它的存储位置在app报名之下,是私有的,别的程序无法直接访问到,另一方面,SharedPreferences是线程安全的,能够保证多线程的安全使用,但是当数据量大,访问频繁的时候,SharedPreferences就显得捉襟见肘
// 在面对简单的业务,一次更新一个键值对
sharedPreferences.edit().putString().commit();
// 在面对复杂的业务,一次更新多个键值对,仍然只进行一次IO操作(文件的写入)
Editor editor = sharedPreferences.edit();
editor.putString();
editor.putBoolean().putInt();
editor.commit(); // commit()才会更新文件
官方提供的commit方法,在多个put 方法执行后,执行commit方法,做到了效率的提高,但是commit方法是同步的,所以,google更建议我们使用apply方法,因为apply方法是异步的,但是这也是出问题的原因所在,
apply()方法设计的初衷是为了规避主线程的I/O操作导致ANR问题的产生,那么,ANR的问题真得到了有效的解决吗?
今日头条团队在这篇文章中,对sp ANR产生的原因进行了探讨
https://mp.weixin.qq.com/s/IFgXvPdiEYDs5cDriApkxQ
“在apply()方法中,首先会创建一个等待锁,根据源码版本的不同,最终更新文件的任务会交给QueuedWork.singleThreadExecutor()单个线程或者HandlerThread去执行,当文件更新完毕后会释放锁。
但当Activity.onStop()以及Service处理onStop等相关方法时,则会执行 QueuedWork.waitToFinish()等待所有的等待锁释放,因此如果SharedPreferences一直没有完成更新任务,有可能会导致卡在主线程,最终超时导致ANR。”
所以当我们数据很少的时候,使用commit 方法是可行的,数据量大的时候使用apply方法,但是当程序异常终止或者系统异常断电,往往会面临着数据恢复等操作,而SP也只能从备份文件中恢复最近一次的操作,由此种种,我们不得不寻求一种更规范的编码习惯,如,尽量少使用SPutils.putxxx()方法,虽然快捷,但是对于系统cpu和IO操作很不友好,我们也要合理选择存储方式,数据量大的时候尽量选择数据库或DataStore
网友评论