【发布时间】:2019-11-27 15:56:00
【问题描述】:
我在生产中遇到了这个恼人的错误,导致我的应用程序崩溃。
我使用PreferenceManager.getDefaultSharedPreferences(context).edit().putLong("key", value).apply(); 来保存我的许多基于用户的偏好
我正在使用implementation 'androidx.preference:preference:1.0.0'
但我还是得到了很多
Fatal Exception: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry + 851(HashMap.java:851)
at java.util.HashMap$KeyIterator.next + 885(HashMap.java:885)
at com.android.internal.util.XmlUtils.writeSetXml + 355(XmlUtils.java:355)
at com.android.internal.util.XmlUtils.writeValueXml + 693(XmlUtils.java:693)
at com.android.internal.util.XmlUtils.writeMapXml + 300(XmlUtils.java:300)
at com.android.internal.util.XmlUtils.writeMapXml + 269(XmlUtils.java:269)
at com.android.internal.util.XmlUtils.writeMapXml + 235(XmlUtils.java:235)
at com.android.internal.util.XmlUtils.writeMapXml + 192(XmlUtils.java:192)
at android.app.SharedPreferencesImpl.writeToFile + 639(SharedPreferencesImpl.java:639)
at android.app.SharedPreferencesImpl.-wrap2(SharedPreferencesImpl.java)
at android.app.SharedPreferencesImpl$2.run + 535(SharedPreferencesImpl.java:535)
at java.util.concurrent.ThreadPoolExecutor.runWorker + 1133(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run + 607(ThreadPoolExecutor.java:607)
at java.lang.Thread.run + 761(Thread.java:761)
我确实知道我的许多偏好更改发生在后台线程中,但是 android api 应该是同步的吧?
我不知道哪些更改会导致崩溃,因为它在 android api 的单独线程中运行,我无法获得有关崩溃的更多信息
有人知道这是什么吗?如何在不将所有apply 变成commit 的情况下解决它?如何获取更多信息?
【问题讨论】:
-
如果你在后台线程中保存首选项,那么你应该使用提交,如果你已经在后台线程中调用apply是没有意义的,这是为了避免UI阻塞,但是如果你已经离开了 UI,没有必要调用 apply。
-
"但是android api应该是同步的吧?" ——理想情况下,是的,但也许不是。
SharedPreferences并没有像 SQLite 那样真正为大量使用而设计。您可能希望在这些写入中添加自己的同步层。如果您将SharedPreferencesI/O 放在存储库单例中,那么您自然就有了同步逻辑的位置。 -
@CommonsWare,用单例创建一个包装器无法解决,因为异常发生在
apply调用之后,它是SharedPreferences的内部线程在做它的工作...... -
抱歉,我还假设存储库会进行自己的线程管理并使用
commit()。