一、持久化方式:
-
DataStore:稳定性
-
MMKV:效率
-
SharedPreferneces
区别:
功能 | MMKV | Jetpack DataStore | SharedPreferneces |
---|---|---|---|
是否阻塞主线程 | 否 | 否 | 是 |
是否线程安全 | 是 | 是 | 是 |
是否支持跨进程 | 是 | 否 | 否 |
是否类型安全 | 否 | 是 | 否 |
是否支持protocol buffers | 是 | 是 | 否 |
是否能监听数据变化 | 否 | 是 | 是 |
二、SharedPreferences存储流程:
-
k,v -> 存储到文件里
-
序列化:XML JSON PROTOBUFF…
-
IO
三、SP的系统源码分析--调用流程
getSharedPreferences("test",MODE_PRIVATE)
-
Context#getSharedPreferences --> Context的实现类 --ContextImpl#getSharedPreferences中去new SharedPreferencesImpl对象 ContextWrapper 用到装饰者模式
-
SharedPreferencesImpl#startLoadFromDisk(),用一个同步代码块synchronized 将 mLoaded = false; (mLoaded -> 加载是否完成)
-
同时启动一个子线程去进行IO操作,子线程中调用loadFromDisk,去进行数据的加载 str = new BufferedInputStream(new FileInputStream(mFile), 16 * 1024) IO体系 用到装饰者模式
-
读数据:读出来之后加载到内存中,放到一个全局的HashMap变量mMap -- 因此SP读取数据的效率是非常高的
-
取数据:
-
每次取数据都会调用一下edit方法,内部都会new EditorImpl
-
得到edit之后,调用put()保存,将k v数据放到临时的map集合里mM
-
保存完了之后调用commit,apply
-
commit:boolean 同步 当CPU忙,达到峰值,数据大,会产生ANR
-
apply: void 异步 也会产生ANR
注意:
在使用SP的时候,不要频繁的调用edit,如在for循环里、view#onDraw,gc频繁运行,可能会导致程序卡顿,如果GC选择的回收对象算法是标记清除算法,可能导致程序出现OOM导致内存碎片的产生。
分析:
Apply异步产生ANR的原因 -- Activity跳转时,apply提交会包装成Runnable:任务 -> QueuedWork:队列 排队执行 ->会执行QueuedWork.waitToFinish:等待QueuedWork中的任务全部执行完
AActivity ->BActivity
A:onPause -> B:onCreate onStart onResume -> A:onStop
疑问:
生命周期是怎么被调起的?/ Activity启动流程
AMS -> Binder -> ActivityThread#ApplicationThread->对应的方法 -> handler -> 调用
总结:
特点 |
说明 |
数据格式 |
XML格式保存 |
初始化 |
子线程使用IO读取整个文件,进行XML解析,存入内存Map集合 |
保存 |
commit同步提交,阻塞主线程;apply异步提交,无法获取结果且可能数据丢失 |
更新 |
把Map中的数据,全部序列化为XML,覆盖文件保存(全量更新) |
优化方向:
-
比XML更精简的数据格式,XML繁琐,冗余数据多,数据量大
-
高效的文件操作 -- 传统IO 高效的NIO(零拷贝) FileChannel,transformTO
-
更优的数据更新方式 -- 局部更新