视频先行

假如你便利看视频,直接去哔哩哔哩或许YouTube看视频就好。

下面是视频内容的脚本整理稿。假如你看了视频,那下面的文稿就不用看了。

正文

这是我在网上找到的一份 Android 键值对存储计划的功用测验比照(数越小越好):

【面试黑洞】Android 的键值对存储有没有最优解?

能够看出,DataStore 的功用比 MMKV 差了一大截。MMKV 是腾讯在 2018 年推出的,而 DataStore 是 Android 官方在 2020 年推出的,并且它的正式版在 2021 年 8 月才发布。一个官方发布的、更(gng)新的库,功用竟然比不过比它早两年发布的、第三方的库。并且咱们能看到,更离谱的是,它乃至还比不过 SharedPreferences 。Android 官方最初之所以推出 DataStore,便是要代替掉 SharedPreferences,并且主要原因之一便是 SharedPreferences 有功用问题,可是测验成果却是它的功用不如 SharedPreferences。

所以,这到底是为什么?

啊,我知道了——由于 Google 是傻逼!

SharedPreferences:不知不觉被厌弃

咱们好,我是扔物线朱凯。

键值对的存储在移动开发里十分常见。比方深色方法的开关、软件语言、字体大小,这些用户偏好设置,很合适用键值对来存。而键值对的存储计划,最传统也最广为人知的便是 Android 自带的 SharedPreferences。它里边的 -Preferences,便是偏好设置的意思,从名字也能看出它开始的定位。

SharedPreferences 运用起来很简略,也没什么问题,咱们就这么用了许多年。——但!渐渐地,有人发现它有一个问题:卡顿,乃至有时分会呈现 ANR。

MMKV:好快!

怎样办?换!2018 年 9 月,腾讯开源了一个叫做 MMKV 的项目。它和 SharedPreferences 相同,都是做键值对存储的,可是它的功用比 SharedPreferences 强许多。真的是强,很,多。在 MMKV 推出之后,许多团队就把键值对存储计划从 SharedPreferences 换到了 MMKV。

DataStore:官方造废物?

再然后,便是又过了两年,Google 自己也表示受不了 SharedPreferences 了,Android 团队发布了 Jetpack 的新库:DataStore,方针直指 SharedPreferences,宣称它便是 Android 官方给出的 SharedPreferences 的代替品。

【面试黑洞】Android 的键值对存储有没有最优解?

代替的理由,Android 团队列了好几条,但不出咱们预料地,「功用」是其中之一:

【面试黑洞】Android 的键值对存储有没有最优解?

也便是说,Android 团队直接扔掉了 SharedPreferences,换了个新东西来提供更优的功用。

可是,问题随之就呈现了:咱们一测验,发现这 DataStore 的功用并不强啊?跟 MMKV 比起来差远了啊?要知道,MMKV 的发布是比 DataStore 早两年的。DataStore 比人家晚两年发布,可是功用却比人家差一大截?乃至,从测验数据来看,它连要被它代替掉的 SharedPreferences 都比不过。这么弱?那它搞个毛啊!

Android 团队吭哧吭哧搞个新东西出来,竟然还没有市场上两年前就呈现的东西强?这是为啥?

首要,必定得扫除「DataStore 是废物」这个或许性。尽管这猛一看、粗一想,显着便是 DataStore 废物、Google 傻逼,可是你细心想想,这或许吗?

那假如不是的话,又是由于什么?——由于你被骗了。

MMKV 的一二三四

被谁骗了?不是被 MMKV 骗了,也不是详细的某个人。作业其实是这样的:

咱们知道 MMKV 最初为什么会被发明出来吗?其实不是为了取代 SharedPreferences。

最早是由于微信的一个需求(来历:MMKV 组件现在开源了):

微信作为一个全民的谈天 App,对话内容中的特别字符所导致的程序溃散是一类很常见、也很需求快速处理的问题;而哪些字符会导致程序溃散,是无法预知的,只能等用户手机上的微信溃散之后,再利用类似时光倒流的回溯行为,看看前次软件溃散的终究一瞬间,用户收到或许发出了什么音讯,再用这些音讯中的文字去测验复现产生过的溃散,终究试出有问题的字符,然后针对性处理。

【面试黑洞】Android 的键值对存储有没有最优解?
那么这个「时光倒流」应该怎样做,就成了问题的关键。咱们要知道,程序中的一切变量都是存活在内存里的,一旦程序溃散,一切变量全都灰飞烟灭。
【面试黑洞】Android 的键值对存储有没有最优解?
所以要想完结「时光倒流」,就需求把想回溯的时光预先记载下来。说人话便是,咱们需求把界面里显现的文字写到手机磁盘里,才能在程序溃散、从头启动之后,经过读取文件的方法来检查。
【面试黑洞】Android 的键值对存储有没有最优解?
更麻烦的是,这种记载的方针是用来回溯查找「导致程序溃散的那段文字」,而一同,正是由于没有人知道哪段文字会导致程序溃散才去做的记载,这就要求每一段文字都需求先写入磁盘、然后再去显现,这样才能确保程序溃散的时分那段导致溃散的文字必定现已被记载到了磁盘。
【面试黑洞】Android 的键值对存储有没有最优解?
对吧?

这就有点难了。

咱们来幻想一下实践场景:

  • 假如用户的微信现在处于一个对话界面中,这时分来了一条新的音讯,这条音讯里或许会包含微信处理不了的字符,导致微信的溃散。
    【面试黑洞】Android 的键值对存储有没有最优解?
  • 而微信为了及时地找出导致溃散的字符或许字符串,所以给程序增加了逻辑:一切的对话内容在显现之前,先保存到磁盘再显现:
val bubble: WxTextView = ...
recordTextToDisk(text) // 显现之前,先保存到磁盘
bubble.setText(text)
  • 那么你想一下,这个「保存到磁盘」的行为,我应该做成同步的仍是异步的?
    【面试黑洞】Android 的键值对存储有没有最优解?
    • 为了不卡主线程,我显然应该做成异步的;
    • 但这是立刻就要显现的文字,假如做成异步的,就极有或许在程序溃散的时分,后台线程还没来得及把文字存到磁盘。这样的话,就无法进行回溯,从而这种记载也就失去了价值。
      【面试黑洞】Android 的键值对存储有没有最优解?
    • 所以从可用性的视点来看,我只能挑选抛弃功用,把它做成同步的,也便是在主线程进行磁盘的写操作。
      【面试黑洞】Android 的键值对存储有没有最优解?
    • 一次磁盘的写操作,花个一两毫秒是很正常的,三五毫秒乃至逾越 10 毫秒也都是有或许的。详细的计划能够挑选 SharedPreferences,也能够挑选数据库,但不管选哪个,只需在主线程去完结这个写操作,这种耗时就绝对无法防止。一帧的时刻也就 16 毫秒而已——那时分还没有高刷,咱们就先不谈高刷了,一帧便是 16 毫秒——16 毫秒里来个写磁盘的操作,用户很或许就会感受到一次卡顿。
  • 这仍是相比照较好的状况。咱们再想一下,假如用户点开了一个活泼的群,这个群里有几百条没看过的音讯:
    • 那么在他点开的一瞬间,是不是界面中会显现出好几条音讯气泡?这几条音讯的内容,哪些需求记载到磁盘?全都要记载的,由于谁也知道哪一条会导致微信的溃散,任何一条都是或许的。
    • 而假如把这几条音讯都记载下来,是不是每条音讯的记载都会触及一次写磁盘的操作?这几回写磁盘行为,是产生在同一帧里的,所以在这一帧里由于记载文字而导致的主线程耗时,也会相比起刚才的比方翻上好几倍,卡顿时刻就相同也会翻上好几倍。
  • 还有更差的状况。假如用户看完这一页之后,决议翻翻谈天记载,看看咱们之前都聊了什么:
    • 这时分,是不是上方每一个新的谈天气泡的呈现,都会触及一次主线程上的写磁盘行为?
    • 而假如用户把手猛地往下一滑,让上面的几十条音讯顺次滑动显现出来,这是不是就会导致一次爆发性的、集中式的对磁盘的写入?
    • 用户的手机,必定会卡爆。

所以这种「高频、同步写入磁盘」的需求,让一切的现有计划都变得不行行了:不管你是用 SharedPreferences 仍是用数据库仍是别的什么,只需你在主线程同步写入磁盘,就必定会卡,并且是很卡。

可是微信仍是有高手,仍是有能想办法的人,终究微信找到了处理计划。他们没有用任何的现成计划,而是运用了一种叫做内存映射mmap())的底层办法。

【面试黑洞】Android 的键值对存储有没有最优解?
它能够让系统为你指定的文件拓荒一块专用的内存,这块内存和文件之间是主动映射、主动同步的关系,你对文件的改动会主动写到这块内存里,对这块内存的改动也会主动写到文件里。
【面试黑洞】Android 的键值对存储有没有最优解?
更多更深的原理,说实话我也不是看得很懂,就不跟咱们装了。但关键是,有了这一层内存作为中间人,咱们就能够用「写入内存」的方法来完结「写入磁盘」的方针了。内存的速度多快呀,耗时简直能够疏忽,这样一下子就把写磁盘形成卡顿的问题处理了。
【面试黑洞】Android 的键值对存储有没有最优解?
并且这个内存映射还有一点很便利的是,尽管这块映射的内存不是实时向对应的文件写入新数据,可是它在程序溃散的时分,并不会随着进程一同被销毁掉,而是会持续有条有理地把它里边还没同步完的内容同步到它所映射的文件里边去。
【面试黑洞】Android 的键值对存储有没有最优解?
至于更下层的原理,我也说了,没看懂,你也别问我。

总归,有了这些特性,内存映射就能够让程序用往内存里写数据的速度完结往磁盘里写数据的实践效果,这样的话,「高频、同步写入磁盘」的需求就完美满意了。不管是用户翻开新的谈天页面,仍是滑动谈天记载来检查谈天历史,用内存映射的方法都能够既实时写入一切即将被烘托的文字,又不会形成界面的卡顿。这种功用,是 SharedPreferences 和数据库都做不到的——顺便提一句,尽管我总在提 SharedPreferences,但其实这种做法本来是先在 iOS 版的微信里应用的,后来才移植到了 Android 版微信。这也是我刚才说的,MMKV 的诞生并不是为了取代 SharedPreferences。

再后来,便是 2018 年,微信把这个叫做 MMKV 的项目开源了。它的名字,我猜便是直白的「Memory-Map based Key-Value(计划)」,根据内存映射的键值对。不过没有找作者求证,假如说错了欢迎指正。

在 MMKV 开源之后,许多团队就把键值对存储计划从 SharedPreferences 搬迁到了 MMKV。为什么?由于它快呀。

MMKV 并不总是快如闪电

不过……作业其实没那么简略。MMKV 尽管大的定位方向和 SharedPreferences 相同,都是关于键值对的存储,但它并不是一个全方位更优的计划。

比方功用。我前面一向在说 MMKV 的功用更强,对吧?但现实上,它并不是任何时分都更强。由于内存映射这种计划是自行办理一块独立的内存,所以它在尺寸的弹性上面就比较受限,这就导致它在写大一点的数据的时分,速度会慢,并且或许会很慢。我做了一份测验:

【面试黑洞】Android 的键值对存储有没有最优解?
在接连 1000 次写入 Int 值的场景中,SharedPreferences 的耗时是 1034 毫秒,也便是 1 秒多一点;而 MMKV 只需 2 毫秒,简直快得离谱;并且最离谱的是,Android 官方最新推出的 DataStore 是 1215 毫秒,竟然比 SharedPreferences 还慢。这个前面我也提过,别人的测验也是这样的成果。

可是,SharedPreferences 是有异步 API 的,而 DataStore 是根据协程的。这就意味着,它们实践占用主线程的时刻是能够低于这份测验出的时刻的,而界面的流通介意的正是主线程的时刻耗费。所以假如我计算的不是全部的耗时,而是主线程的耗时,那么计算出的 SharedPreferencesDataStore 的耗时将会大幅减缩:

【面试黑洞】Android 的键值对存储有没有最优解?
仍是比 MMKV 慢许多,是吧?可是这是关于 Int类型的高频写入,Int 数据是很小的。而假如我把写入的内容换生长字符串,再做一次测验:
【面试黑洞】Android 的键值对存储有没有最优解?
MMKV 就不具有优势了,反而成了耗时最久的;而这时分的冠军就成了 DataStore,并且是遥遥领先。这也便是我在开头说的:你或许被骗了。被谁骗了?被「耗时」这个词:咱们重视功用,考量的当然是耗时,但要明确:是主线程的耗时。所以视频开头的那张图,是不具有任何参考意义的。
【面试黑洞】Android 的键值对存储有没有最优解?

但其实,它们都够快了

不过在换成了这种只看主线程的耗时的比照计划之后,咱们会发现谁是冠军其实并不是很重要,由于从终究的数据来看,三种计划都不是很慢。尽管这半秒左右的主线程耗时看起来很可怕,可是要知道这是 1000 次接连写入的耗时,而咱们在真实写程序的时分,怎样会一次性做 1000 次的长字符串的写入?所以真实在项目中的键值对写入的耗时,不管你选哪个计划,都会比这份测验成果的耗时少得多的,都少到了能够疏忽的程度,这是关键。

各自的优势和缺点

那……已然它们的耗时都少到了能够疏忽,不便是选谁都行?那倒不是。

MMKV 优势:写速度极快

咱们来看一个 MMKV 官方给出的数据比照图:

【面试黑洞】Android 的键值对存储有没有最优解?
从这张图看来,SharedPreferences 的耗时是 MMKV 的接近 60 倍。很显着,假如 SharedPreferences 用异步的 API 也便是 apply() 来保存的话,是不或许有这么差的功用的,这个必定是运用同步的 commit() 的功用来做的比照。那么为什么 MMKV 官方会这样做比照呢?这个又要提到它的诞生场景了:MMKV 开始的功用是在文字显现之前先把它记载到磁盘,然后假如接下来这个文字显现失败导致程序溃散,稍后就能够从磁盘里把这段文字康复出来,进行剖析。而刚才我也说过,这种场景的特别性在于,导致程序溃散的文字往往是刚刚被记载下来,程序就溃散了,所以假如选用异步处理的计划,就很有或许在文字还没来得及真实存储到磁盘的时分程序就产生了溃散,那就没办法把它康复出来进行剖析了。因而这样的场景,是不能承受异步处理的计划的,只能同步进行。所以 MMKV 介意的,便是同步处理机制下的耗时,它不介意异步,由于它不承受异步。

而在同步处理的机制下,MMKV 的功用优势就太显着了。原因上面说过了,它写入内存就简直等于写入了磁盘,所以速度巨快无比。这便是 MMKV 的优势之一:极高的同步写入磁盘的功用。

别的 MMKV 还有个特点是,它的更新并不像 SharedPreferences 那样全量从头写入磁盘,而是只把要更新的键值对写入,也便是所谓的增量式更新。这也会给它带来一些功用优势,不过这个优势并不算太核心,由于 SharedPreferences 尽管是全量更新的方法,但只需把保存的数据用适宜的逻辑拆分到多个不同的文件里,全量更新并不会对功用形成太大的连累。所以这个功用优势尽管有,但并不是关键。

还有刚才提到的,关于大字符串的场景,MMKV 的写入功用并不算快,乃至在咱们的测验成果里是最慢的,对吧?这一点算是下风。可是实事求是地说,咱们在开发里不太或许接连不断地去写入大字符串吧?所以这个功用下风尽管有,但也并不是关键。

整体来说,MMKV 比起 SharedPreferences 和 DataStore 来说,在写入小数据的状况下,具有很高的写入功用,这就让高频写入的场景十分合适运用 MMKV 来处理。因而假如你的项目里也有像微信的溃散回溯的这种高频写入的需求,MMKV 就很或许是你的最佳计划。而假如你除了「高频写入」,还和微信相同要求「同步写入」,那 MMKV 就或许是你的仅有挑选了。不过,假如你真的主要是存储大字符串的——例如你写的是一个文本编辑软件,需求保存的总是大块的文本——那么用 MMKV 不必定会更快了,乃至或许会比较慢。

MMKV 优势:支撑多进程

别的,MMKV 还有一个巨大的优势:它支撑多进程。

行业界也有许多公司选用 MMKV 并不是由于它快,而是由于它支撑多进程。SharedPreferences 是不支撑多进程的,DataStore 也不支撑——从 DataStore 提交的代码来看,它现已在加入多进程的支撑了,但现在还没有完结。所以假如你们公司的 App 是需求在多个进程里拜访键值对数据,那么 MMKV 是你仅有的挑选。

MMKV 下风:丢数据

除了速度快和支撑多进程这两个优势之外,MMKV 也有一个缺点:它会丢数据。

任何的操作系统、任何的软件,在往磁盘写数据的进程中假如产生了意外——例如程序溃散,或许断电关机——磁盘里的文件就会以这种写了一半的、不完整的方法被保存。写了一半的数据怎样用啊?没法用,这便是文件的损坏。这种问题是不或许防止的,MMKV 尽管由于底层机制的原因,在程序溃散的时分不会影响数据往磁盘的写入,但断电关机之类的操作系统等级的溃散,MMKV 就没办法了,文件照样会损坏。关于这种文件损坏,SharedPreferences 和 DataStore 的应对方法是在每次写入新数据之前都对现有文件做一次主动备份,这样在产生了意外呈现了文件损坏之后,它们就会把备份的数据康复过来;而 MMKV,没有这种主动的备份和康复,那么当文件产生了损坏,数据就丢了,之前保存的各种信息只能被重置。也便是说,MMKV 是仅有会丢数据的计划。

或许会有人好奇,为什么 MMKV 不做全主动的备份和康复。我的猜测是这样的:MMKV 底层的原理是内存映射,而内存映射这种方法,它从内存往磁盘里同步写入的进程并不是实时的,也便是说并不是每次咱们写入到映射的内存里就会当即从这块内存写入到磁盘,而是会有一些滞后。而假如咱们要做全主动的备份,那就需求每次往内存里写入之后,当即手动把内存里最新的数据同步到磁盘。但这就和 MMKV 的定位不符了:由于这种「同步」本质上便是一次从内存到磁盘的写入,并且是同步的写入;而 MMKV 是要高频写入的,假如在高频写入内存的一同,还要实时地把数据从内存同步到磁盘,就会一下子把写入速度从内存等级下降到磁盘等级,MMKV 的功用优势也就化为乌有了。所以从原理上,主动备份是个很难完结的需求,由于它和 MMKV 的定位是对立的。不过正好 MMKV 所要记载的这些要显现的文字,也并不是不能丢掉的内容——真要是丢了就丢了呗,横竖是溃散日志,丢了就不要了,我下次启动程序之后持续记载便是了——所以已然要求有必要高频写入而导致很难完结主动备份,并且也的确能承受由于不做主动备份而导致的数据损坏,那就干脆不做主动备份了。不过这也是我猜的啊,咱们假如有不同定见欢迎留言谈论指正。

所以假如你要用 MMKV,必定要记得只能用它来存能够承受丢掉、不那么重要的数据。或许你也能够挑选对数据进行定期的手动备份——全主动的实时备份应该是会严峻影响功用的,不过我没试过,你假如有兴趣能够试试。别的据我所知,国内在运用 MMKV 的团队里,简直没有对 MMKV 数据做了备份和康复的处理的。

那么提到这里,很容易引出一个问题:微信自己就不怕丢数据吗?(大字:微信就不怕丢数据?)关于这一点,我信任,微信绝对不会把用户登录状况相关的信息用 MMKV 保存并且不做任何的备份,由于这必定会导致每天都会有一些用户在新一次翻开微信的时分发现自己登出了。这会是十分差的用户体会,所以微信必定不会让这种事产生。至于一些简略的用户设置,那我就不清楚了。比方深色主题重要吗?这是个不好说的作业:某个用户在翻开软件的时分,发现自己之前设置的深色主题失效了,软件忽然变回了亮色计划,这必定是不舒服的事;但咱们要知道,MMKV 的文件损坏终归是个概率极低的事情,所以偶然地产生一次这样的事情在产品的视点是否能够承受,那或许是需求产品团队本身做一个综合考量的事了。关于不同的产品和团队,也许不行承受,也许无伤大雅。而关于你所开发的产品应该是怎样的判别,就得各位自己和团队去商量了。所以像深色主题这种「能够重要也能够不重要」的信息,用不用 MMKV 保存、用的时分做不做备份,咱们需求自己去判别。

总归,咱们要知道这件事:MMKV 是有数据损坏的概率的,这个在 MMKV 的官方文档就有说明:MMKV 的 GitHub wiki 页面显现,微信的 iOS 版平均每天有 70 万次的数据校验不经过(即数据损坏)。这仍是 2020 年的数据,现在或许会更多。

【面试黑洞】Android 的键值对存储有没有最优解?
所以咱们在运用 MMKV 的时分,必定要考虑到这个问题,你要知道这件事。至于详细的应对,是承受它、坏就坏了,仍是要仔细应对、做好备份和康复,这便是咱们自己的决议计划了。

SharedPreferences 的优势:不丢数据

好,那么说完了 MMKV,我来说一下 SharedPreferences,这个最传统的计划。

它有什么优势呢?——它没有优势。跟 MMKV 比起来,它不会丢数据,这个却是它比 MMKV 强的地方,可是我觉得更应该归为 MMKV 的下风,而不是 SharedPreferences 的优势,由于只需 MMKV 会丢数据嘛,是吧?

不过不管是这个的优势仍是那个的下风,假如你不期望丢数据,并且也不想花时刻去做手动的备份和康复,一同关于 MMKV 的超高写入功用以及多进程支撑都没有需求,那你其实更应该挑选 SharedPreferences,而不是 MMKV。对吧?

SharedPreferences 的下风:卡顿

但更进一步地说:假如你挑选了 SharedPreferences,那么你更应该考虑 DataStore。由于 DataStore 是一个彻底逾越了 SharedPreferences 的存在。你看 SharedPreferences 和 MMKV 它俩是各有好坏对吧?尽管 MMKV 简直完胜,可是究竟 SharedPreferences 不会丢数据呀,所以它俩是各有好坏的。但当 DataStore 和 SharedPreferences 比起来,那便是 DataStore 完胜了。这其实也很合理,由于 DataStore 被发明出来,便是用于代替掉 SharedPreferences 的;而 MMKV 不相同,它的诞生有它独特的使命,它是为了「高频同步写入」而诞生的,所以不能全视点胜过 SharedPreferences 也很正常。

咱们还说回 DataStore。DataStore 被发明出来的方针便是代替 SharedPreferences,而它处理的 SharedPreferences 最大的问题有两点:一是功用问题,二是回调问题。

先说功用问题:SharedPreferences 尽管能够用异步的方法来保存更改,以此来防止 I/O 操作所导致的主线程的耗时;但在 Activity 启动和关闭的时分,Activity 会等候这些异步提交完结保存之后再持续,这就相当于把异步操作转换成同步操作了,从而会导致卡顿乃至 ANR(程序未呼应)。这是为了确保数据的一致性而不得不做的决议,但它也的确成为了 SharedPreferences 的一个缺点。而 MMKV 和 DataStore 用不同的方法各自都处理了这个问题——现实上,最初 MMKV 被发布的时分之所以在业界有相当大的反响,便是由于它处理了 SharedPreferences 的卡顿和 ANR 的问题。

不过有一点我的观点或许和一些人不同:SharedPreferences 所导致的卡顿和 ANR,其实并不是个很大的问题。它和 MMKV 的数据损坏相同,都是十分低概率的事情。它俩最大的区别在于其实是政治上的:SharedPreferences 的卡顿很容易被大公司的功用剖析后台监测到,所以不处理的话会扣绩效,而处理掉它会提升绩效;而 MMKV 的数据损坏是无法被监测到的,所以……哈?现实上,咱们想一下:卡顿和数据损坏,哪个更严峻?当然是数据损坏了,对吧。

其实除了写数据时的卡顿,SharedPreferences 在读取数据的时分也会卡顿。尽管它的文件加载进程是在后台进行的,但假如代码在它加载完结之前就去测验读取键值对,线程就会被卡住,直到文件加载完结,而假如这个读取的进程产生在主线程,就会形成界面卡顿,并且数据文件越大就会越卡。这种卡顿,不是 SharedPreferences 独有的,MMKV 也是存在的,由于它初始化的进程相同也是从磁盘里读取文件,并且是一股脑把整个文件读完,所以耗时并不会比 SharedPreferences 少。而 DataStore,就没有这种问题。DataStore 不管是读文件仍是写文件,都是用的协程在后台进行读写,一切的 I/O 操作都是在后台线程产生的,所以不管读仍是写,都不会卡主线程。

简略来说,SharedPreferences 会有卡顿的问题,这个问题 MMKV 处理了一部分(写时的卡顿),而 DataStore 彻底处理了。所以假如你的方针在于全方位的功用,那么你应该考虑的是 DataStore,由于它是仅有彻底不会卡顿的。

SharedPreferences 的下风:回调

DataStore 处理的 SharedPreferences 的另一个问题便是回调。SharedPreferences 假如运用同步方法来保存更改(commit()),会导致主线程的耗时;但假如运用异步的方法,给它加回调又很不便利,也便是假如你想做一些「等这个异步提交完结之后再怎样怎样样」的作业,会很麻烦。

而 DataStore 由于是用协程来做的,线程的切换是十分简略的,你就把「保存完结之后做什么」直接写在保存代码的下方就能够了,很直观、很简略。

比照来说,MMKV 尽管没有运用协程,可是它太快了,所以大多数时分并不需求切线程也不会卡顿。总归,在这件事上,只需 SharedPreferences 最弱。

总结

区别大概便是这么些区别了,大致总结一下便是:

假如你有多进程支撑的需求,MMKV 是你仅有的挑选;假如你有高频写入的需求,你也应该优先考虑 MMKV。但假如你运用 MMKV,必定要知道它是或许丢掉数据的,不过概率很低便是了,所以你要在权衡之后做好决议:是自行完结数据的备份和康复计划,仍是直接承受丢数据的现实,在每次丢掉数据之后帮用户把相应的数据进行初始化。当然了,一个最鸡贼的做法是:横竖数据监测不会监测到 MMKV 的数据丢掉,又不影响绩效,那就不管它呗!不过我个人是不太附和这种战略的,有点不负责哈。

别的,假如你没有多进程的需求,也没有高频写入的需求,DataStore 作为功用最完美的计划,应该优先被考虑。由于它在任何时分都不会卡顿,而 MMKV 在写大字符串和初度加载文件的时分是或许会卡顿的,并且初度加载文件的卡顿不是概率性的,只需文件大到了引起卡顿的程度,便是 100% 的卡顿。不过假如你的团队没有在用协程,乃至没有在用 Kotlin,那 DataStore 也暂时不合适你们,由于它是彻底依靠 Kotlin 协程来完结和运用的。

哦对了,其实我今日说的 DataStore 仅仅面向简略键值对存储的 DataStore 计划,它的全称叫 Preferences DataStore,而 DataStore 还有用于保存结构化数据的计划,叫做 Proto DataStore,它内部用的是 Protocol Buffer 作为数据结构的支撑。可是这个有点跑题,我就不展开了。

至于 SharedPreferences 嘛,在这个时代,它真的能够被抛弃了。除非——像我刚说的——假如你们还没在用协程,那 SharedPreferences 或许还能苟延残喘一下。

今日的内容便是这些了。假如你喜欢我的内容,还请多多点赞转发收藏分享,今后我会讲更多和 Android 开发相关的风趣、有用的分享。重视我,不错过我的任何新内容。我是扔物线,我不和你比凹凸,我只助你生长。咱们下期见。