Open Moosphan opened 5 years ago
commit是同步写入,会返回执行结果,apply方法是异步写入,并不会返回执行结果;但是SharedPreferences文件的写入是全量写入,即使只是修改了其中一条key-value,也会执行全部的写入操作,因为SharedPreferences只能用于存储体积较小的数据,太大了就容易引发OOM,同时如果需要修改多条数据,必须使用Editor来一次性完成修改再提交
SharedPreferences 是线程安全的 进程不安全的, commit 是同步写入,apply是异步写入。
SharedPreferences 是线程安全的 进程不安全的, commit 是同步写入有返回值,apply是异步写入。
由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。
SP 是线程安全,非进程安全。commit 和 apply 的方法里面都一个 commitToMemory 方法,即把更新同步到内容。至于落地磁盘,commit 也并非完全同步,如果 commit 前有 apply 还未落盘,commit 会异步等待 apply 落盘之后在执行,内部通过一个计数器来判断。 详细见:https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/SharedPreferences.md
1.SharePreferences是线程安全的 里面的方法有大量的synchronized来保障。
2.SharePreferences不是进程安全的 即使你用了MODE_MULTI_PROCESS 。
3.第一次getSharePreference会读取磁盘文件,异步读取,写入到内存中,后续的getSharePreference都是从内存中拿了。
4.第一次读取完毕之前 所有的get/set请求都会被卡住 等待读取完毕后再执行,所以第一次读取会有ANR风险。
5.所有的get都是从内存中读取。
6.提交都是 写入到内存和磁盘中 。apply跟commit的区别在于
apply 是内存同步 然后磁盘异步写入任务放到一个单线程队列中 等待调用。方法无返回 即void
commit 内存同步 只不过要等待磁盘写入结束才返回 直接返回写入成功状态 true or false
7.从 Android N 开始, 不再支持 MODE_WORLD_READABLE & MODE_WORLD_WRITEABLE. 一旦指定, 会抛异常 。也不要用MODE_MULTI_PROCESS 迟早被放弃。
8.每次commit/apply都会把全部数据一次性写入到磁盘,即没有增量写入的概念 。 所以单个文件千万不要太大 否则会严重影响性能。
建议用微信的第三方MMKV来替代SharePreference
1.SharePreferences是线程安全的 里面的方法有大量的synchronized来保障。 2.commit是同步写入,会返回执行结果,apply方法是异步写入,并不会返回执行结果; 3.SharePreferences不是进程安全的 4.SharedPreferences是以XML的格式以文件的方式自动保存的,在DDMS中的File Explorer中展开到/data/data/<package name>/shared_prefs下,可以看到一个叫做SETTING_Infos.xml的文件 总结比较不错文章可以看下面具体分析: http://gityuan.com/2017/06/18/SharedPreferences/ 我的项目应用场景:保存用户名字,密码,手势密码,json字符串, 如果非要保存一个你都不确定大小的东西我建议是,你单独开启一个新的sharedprefernces来保存,如果想把一个集合保存起来怎么保存,如果想把集合中在套一个map集合怎么保存, private void setCateg(List<Map<String, String>> datalist) { Gson gson = new Gson(); String s1 = gson.toJson(datalist); LSharePreference.getInstance(getActivity()).setString(SharePreferenceName.PROGRESS, s1);
} /**
这样好处,跟坏,你是怎么认为,你觉的会怎么样?
楼上都说的很清楚了,这里补充一个问题,
SharedPreferences优化建议: 来源:http://gityuan.com/2017/06/18/SharedPreferences/#%E4%BA%94-%E6%80%BB%E7%BB%93
全量写入:无论是commit还是apply都是全量写入,所以最好一次性操作完数据再提交 安全:线程安全,进程不安全 同步异步:commit同步提交,apply异步提交 卡顿:如果文件太大,加载时间会边长,影响启动速度,处理数据不能太大,onPause的是会检查是否存储完毕
SharedPreferences是线程安全的 进程不安全 用于存储体积小的数据 apply异步提交先提交到内存 而后在异步提交到硬盘 commit是同步提交到硬盘并返回结果
SharedPreferences为什么是进程不安全? 1) SharedPreferences是进程不安全的,因为没有使用跨进程的锁。既然是进程不安全,那么久有可能在多进程操作的时候发生数据异常。
2) 我们有两个办法能保证进程安全:
使用跨进程组件,也就是ContentProvider,这也是官方推荐的做法。通过ContentProvider对多进程进行了处理,使得不同进程都是通过ContentProvider访问SharedPreferences。 加文件锁,由于SharedPreferences的本质是读写文件,所以我们对文件加锁,就能保证进程安全了。
context.getSharedPreferences()开始追踪的话,可以去到ContextImpl的getSharedPreferences(),最终发现SharedPreferencesImpl这个SharedPreferences的实现类,在代码中可以看到读写操作时都有大量的synchronized,因此它是线程安全的