Booster Shared Preferences 优化
背景
在 booster v0.1.5 版本其实就已经提供了针对 SharedPreferences 的优化,只不过优化的幅度比较小,毕竟 SharedPreferences 在 Android 中应用得过于广泛,所以,对它的优化非常非常谨慎,以至于我们经过了线上好几个版本的验证,才推出最新的优化方案。
至于为什么要对 SharedPreferences 做优化,我想做过 Android 开发的同学都清楚 SharedPreferences 的设计一直为人所诟病,其实,SharedPreferences 从一开始被 Google 的工程师设计出来并不是像现在这样用的,只不过后来被大家玩儿坏了,以至于出现了各种卡顿、ANR。
booster v0.1.5 的优化方案
booster v0.1.5 推出的针对 SharedPreferences 的优化,主要是将 Editor.apply() 替换成 Editor.commit() 并在子线程中执行,代码如下:
1 | public class ShadowEditor { |
至于为什么要将 Editor.apply() 替换成异步 Editor.commit(),可以看看这篇文章:http://www.cloudchou.com/android/post-988.html
booster v0.2.0 的优化方案
booster v0.2.0 又进一步对 SharedPreferences 做了优化,当调用了 Editor.commit() 但是其返回值如果没使用,就将 Editor.commit() 放到子线程中执行,代码如下:
1 | override fun transform(context: TransformContext, klass: ClassNode): ClassNode { |
数据一致性问题
前两种优化方案虽然能一定程度上解决卡顿和 ANR 的问题,但其实是有 bug 的,比如像下面这段代码:
1 | SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE); |
大家有没有发现?刚 put
完,立即 get
,这时候很有可能是取不到 put
的值的,因为 Editor.commit() 很有可能还在线程池中排队,只不过一般很少有代码写成这样,但是还是避免不了这样的情况会发生,所以,我们推出了新的优化方案,目的有以下几点:
- 解决 SharedPreferences 引起的卡顿和 ANR;
- 解决 SharedPreferences 在进程间的数据共享问题;
- 修复之前的版本中遗留的数据一致性问题;
终极方案
想要彻底解决 SharedPreferences 问题,就需要避开原生实现的各种坑,如:
- Editor.apply() 导致的 ANR;
- Editor.commit() 导致主线程卡顿;
- 频繁异步 Editor.commit() 导致主线程卡顿甚至 ANR;
- 进程间无法及时同步数据;
所以,针对此问题 booster 的解决方案是—— BoosterSharedPreferences,通过 SharedPreferencesTransformer 将所有调用 Context.getSharedPreferences(String, int)
的指令替换成 ShadowSharedPreferences.getSharedPreferences(Context, String, int)
,代码如下:
1 | public class ShadowSharedPreferences { |
在 BoosterSharedPreferences 中,对 SharedPreferences 进行了缓存,这样能够大幅的提升性能。
1 | public static SharedPreferences getSharedPreferences(final String name) { |
- 本文链接:https://johnsonlee.io/2019/11/12/booster-transform-shared-preferences/
- 版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。