SharedPreferences中的commit()和apply()有什么区别


432

SharedPreferences在我的Android应用程序中使用。我正在使用共享首选项中的commit()apply()方法。当我使用AVD 2.3时,它没有显示错误,但是当我在AVD 2.1中运行代码时,apply()方法显示了错误。

那么这两者有什么区别?并且仅通过使用commit()就可以毫无问题地存储首选项值吗?


115
这已经有一年的历史了,但是无论如何我都会对此发表评论,尽管也许显而易见,但是没有答案能说明这一点:apply()commit()同步的同时异步执行磁盘I / O。因此,您实际上不应该commit()从UI线程进行调用。
michiakig 2012年

值得注意的是,当使用多个SharedPreferences.Editor对象时,最后一个调用成功apply()。因此,如果您确保应用程序仅使用一个SharedPreferences.Editor,则可以apply()代替commit()安全使用。
aoeu

2
按照Android Studio Lint警告:commit()将立即并同步保存数据。但是,apply()将异步保存它(在后台),从而提高了性能。这就是为什么如果您不关心它的返回类型(无论数据是否成功保存),则apply()优先于commit()的原因。
拉胡尔·雷纳

使用时是否可以禁用Lint警告commit()
QED19年

Answers:


654

apply()是在2.3中添加的,它的提交没有返回表示成功或失败的布尔值。

commit()如果保存有效,则返回true,否则返回false

apply() 之所以加入,是因为Android开发者团队注意到几乎没有人注意到返回值,因此apply更快,因为它是异步的。

http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply()


8
这个答案是正确的,但我想上面的@spacemanaki的评论也正确,其中包含有价值的信息
Aksel Fatih

58
commit()立即将其数据写入持久性存储,而apply()将在后台对其进行处理。
capt.swag

18
它会产生竞争条件吗?
ChrisMcJava 2015年

42
如果我使用apply()编写某些内容,然后尝试立即读取它会怎样?读书能保证给我最新的价值吗?文档说如果在您触发apply()之后发生另一个commit(),则该commit()将阻塞,直到apply()持久化到磁盘上为止,这清楚地表明,在进行“写入”操作时不会发生此问题,但是如果您紧接着又要写作和阅读呢?从我的测试中,返回了最新值,但是我想知道这是否是100%保证的。
Tiago

22
它是安全的替换)与提交申请(任何情况下()见developer.android.com/reference/android/content/...
狄格兰Sarkisian

221

tl; dr:

  • commit()同步写入数据(阻塞从其调用的线程)。然后它会通知您有关操作成功的信息。
  • apply()调度要异步写入的数据。它不会通知您有关操作成功的信息。
  • 如果使用保存apply()立即通过任何getX方法读取,则将返回值!
  • 如果您apply()在某个时间调用了该命令,并且该命令仍在执行,则对的所有调用都commit()将阻塞,直到所有过去的apply-call 当前的commit-call完成为止。

来自SharedPreferences.Editor文档的更多深入信息:

commit()会将其首选项同步写到持久性存储中的方式不同apply()立即将其更改提交到内存中的SharedPreferences,但会启动对磁盘的异步提交,并且不会收到任何失败通知。如果此SharedPreferences上的另一个编辑器在apply()仍未完成的情况下执行常规commit(),则commit()将阻塞,直到所有异步提交以及提交本身都完成为止。

由于SharedPreferences实例是流程中的单例实例,因此如果您已经忽略了返回值,则可以用apply()替换任何commit()实例是安全的。

不应直接实现SharedPreferences.Editor接口。但是,如果您以前确实实现了它,现在却遇到有关缺少apply()的错误,则只需从apply()调用commit()即可。


19
这是一个更好的答案,因为它提到了apply()异步且未决的写操作会阻止将来对的调用commit()
spaaarky21

22

我在使用apply()而不是commit()时遇到了一些问题。如之前在其他响应中所述,apply()是异步的。我遇到的问题是,对“字符串集”首选项形成的更改永远不会写入持久性内存。

如果您“强行扣留”该程序,或者在我安装有Android 4.1的设备上安装的ROM中,由于内存必要而导致该进程被系统终止,则会发生这种情况。

如果您希望保留首选项,建议使用“ commit()”而不是“ apply()”。


您确定您的问题与并发线程无关吗?发送apply()之后,您必须等待一段时间才能读取所添加的内容,否则UI线程将尝试在apply()的辅助线程提交更改之前进行读取。
Marco Altran 2014年


@JoseLSegura-文档另有建议: developer.android.com/intl/ja/reference/android/content / ... “您无需担心Android组件的生命周期以及它们与apply()写入磁盘的交互。该框架确保在切换状态之前完成对apply()的运行中磁盘写入。” 我想知道您所看到的是否是Android中的错误,如果是,则是否已在较新版本中修复。
ToolmakerSteve

使用库“ ProcessPhoenix”重置我的应用程序时,我遇到了同样的问题。我在执行重置之前保存了首选项,但是“应用”无效。
ElYeante '19

14

使用apply()。

它将更改立即写入RAM,然后等待,然后将其写入内部存储(实际首选项文件)。提交将更改同步并直接写入文件。


14
  • commit()是同步的,apply()是异步的

  • apply() 是void函数。

  • commit() 如果新值已成功写入持久性存储,则返回true。

  • apply() 保证状态切换前完成,您无需担心Android组件的生命周期

如果您不使用从主线程返回的值,commit()而在commit()主线程中使用,请使用apply()而不是 commit()


13

该文档给出的区别的一个很好的解释apply()commit()

与不同commit(),后者将其首选项同步地写到持久性存储中,而是立即apply()将其更改提交到内存中 SharedPreferences,但是开始对磁盘进行异步提交,并且不会收到任何故障通知。如果与此相关的其他编辑器在a 仍未完成时SharedPreferences执行常规操作,则will会阻塞,直到所有异步提交以及提交本身完成为止。由于实例是流程中的单例实例,因此如果您已经忽略了返回值,则可以用替换任何实例 。commit()apply()commit()SharedPreferencescommit()apply()


6

从javadoc:

与commit()将其首选项同步写到持久性存储中的方式不同,apply()立即将其更改提交到内存中的SharedPreferences,但是将异步提交到磁盘,并且不会收到任何失败通知。如果此SharedPreferences上的另一个编辑器在仍未执行> apply()的情况下进行常规commit(),则commit()将阻塞,直到所有异步提交以及提交本身完成为止


1

commit()和apply()之间的区别

当我们使用SharedPreference时,我们可能会对这两个术语感到困惑。基本上它们可能是相同的,因此让我们澄清一下commit()和apply()的区别。

1.返回值:

apply()提交而不返回表示成功或失败的布尔值。 commit()如果保存有效,则返回true,否则返回false。

  1. 速度:

apply()是比较快的。 commit()比较慢

  1. 异步与同步:

apply():异步 commit():同步

  1. 原子:

apply():原子 commit():原子

  1. 错误通知:

apply():否 commit():是


如何apply()比“更快” commit()?它们本质上表示将放入线程Looper中的同一任务。commit()将该任务放在主Looper中,同时apply()将其放在后台,从而使主Looper 摆脱磁盘I / O任务。
Taseer

与commit()会将其首选项同步写到持久性存储中的方式不同,apply()会立即将其更改提交到内存中的SharedPreferences,但是会启动对磁盘的异步提交,并且不会收到任何失败通知。如果此SharedPreferences上的其他编辑器在apply()仍未完成的情况下执行常规commit(),则commit()将阻塞,直到所有异步提交以及提交本身都完成为止,请参阅DOC developer.android.com/reference/ android / content /…
Chanaka Weerasinghe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.