android - 异步 LiveData/Room 查询会导致竞争条件吗?

标签 android multithreading android-room android-livedata

考虑一个包含两个 fragment 的简单 Activity :

  • RecordListFragment : 一个 RecyclerView绑定(bind)到LiveData<Record>通过 @Query和一个调用 @Delete 的按钮查询 Record
  • RecordEditFragment : 几个用于更改记录的小部件和一个调用 @Insert 的保存按钮或 @Update查询 Record

  • documentation for RoomDatabase.Builder#allowMainThreadQueries状态:

    Room ensures that Database is never accessed on the main thread because it may lock the main thread and trigger an ANR. If you need to access the database from the main thread, you should always use async alternatives or manually move the call to a background thread.



    我发现的每个教程/博客/示例都声明相同,您不应该使用数据库工作阻塞 UI 线程。我的直觉不同意:在从数据库中插入或删除数据时,我最想要的就是有一种简单的方法来阻止用户干扰。

    如果所有数据库访问都发生在工作线程上,那么想到的一种可能的事件顺序是:
  • 用户删除Record aRecordListFragment
  • 用户设法输入 RecordEditFragment对于 Record a
  • 后台线程执行删除
  • 用户尝试保存/更新不存在的 Record a
  • 繁荣

  • 另一种情况是:
  • 用户更新现有的 Record a来自 RecordEditFragment , 过渡到 RecordListFragment
  • 在列表有机会更新之前,用户重新输入 RecordEditFragment对于 Record a
  • RecordEditFragment使用旧数据打开
  • 后台线程执行保存
  • 繁荣

  • 这些是异步工作时的经典竞争条件,我无法想象这实际上是 Android 上的最佳实践,但我找不到任何其他说明的文档。这些情况是否真的可能发生,或者 Android 是否会阻止此类事情的发生?为什么不为简单的任务(例如插入记录)阻止 UI 以防止出现竞争条件?

    最佳答案

    您可以在不“阻止 UI”的情况下阻止用户干扰任务。
    你说:

    There's nothing more I want when inserting or deleting data from a database than having an easy way to block the user from interfering


    您绝对可以更改 UI,这样它就不会让用户在您有后台进程或任何您想要运行的东西时做某事。这不是“阻止用户界面”的意思。阻止 UI 意味着阻止 UI 线程 从能够操作。
    现代 Android 开发,包括 Kotlin Coroutines 的内置功能,在某些方面可以防止您阻塞 UI 线程,甚至在您修复代码之前不进行编译。但是有可能您可能支持旧版本的 Android,或者不使用这些语言功能,因此您仍然可以不编写在 UI 线程上运行缓慢的代码。这样一来,即使其他线程中发生的事情可能需要一段时间,您的 UI 也似乎是响应式的。
    因此,如果您需要写入 RoomDB 或运行网络请求,则应该在另一个线程(如 IO 线程)上进行。
    https://developer.android.com/guide/components/processes-and-threads
    有关 Android 进程和线程的更多信息(特别是阅读有关线程的部分),或者有关 Kotlin 协程如何帮助的更多具体信息,请查看 https://developer.android.com/kotlin/coroutines-adv
    特别是,请注意上面 Android 开发人员链接中的以下引用:

    When the thread is blocked, no events can be dispatched, including drawing events ...

    ... the Android UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:

    Do not block the UI thread

    Do not access the Android UI toolkit from outside the UI thread


    所以继续在另一个线程上启动该后台工作,并更改您的 UI 以显示它正在做某事,直到另一个线程完成。然后,您阻止了用户的干扰,并且您还使应用程序以一种不会出现故障的方式工作。

    关于android - 异步 LiveData/Room 查询会导致竞争条件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58035924/

    相关文章:

    java - 如何在 Android 中制作 Java 线程转储?

    android - Linkify、ListView 和 ActionMode。常规文本不再可点击

    java - 即使所有的latch.countdown()都被调用,程序仍继续执行

    android - 如何使用 FTS4 修复 SQLite Android 上的错误 "Wrong number of arguments to function rank()"?

    android - 房间迁移失败回退android

    android - 如何在 Android 中立即从服务器获取新数据?

    android - 删除并安装应用程序后取回共享首选项

    android - Onclick 不会在 CardView 上触发

    c# - 什么时候允许跨线程访问,什么时候不允许?

    java - 干扰线程