Рассмотрим простое действие, содержащее два фрагмента:
RecordListFragment
: RecyclerView
, связанный с LiveData<Record>
через @Query
и кнопку, которая вызывает запрос @Delete
дляRecord
RecordEditFragment
: несколько виджетов для изменения записи и кнопка сохранения, которая вызывает запрос @Insert
или @Update
для Record
The Документация для RoomDatabase.Builder # allowMainThreadQueries гласит:
Комната гарантирует, что к базе данных никогда не будет доступа в главном потоке, поскольку она может заблокировать основной поток и вызвать ANR.Если вам нужен доступ к базе данных из основного потока, вы всегда должны использовать асинхронные альтернативы или вручную перемещать вызов в фоновый поток.
Каждый найденный мной учебник / блог / пример гласит:не должен блокировать поток пользовательского интерфейса при работе с базой данных.Мой инстинкт не согласен: при вставке или удалении данных из базы данных мне больше ничего не нужно, кроме как иметь простой способ заблокировать вмешательство пользователя.
Если весь доступ к базе данных происходит в рабочем потоке, возможен один порядок событий,На ум приходит:
- Пользователь удаляет
Record a
на RecordListFragment
- Пользователю удается ввести
RecordEditFragment
для Record a
- Фоновый поток выполняет удаление
- Пользователь пытается сохранить / обновить несуществующий
Record a
- Boom
Другой сценарий:
- Пользователь обновляет существующий
Record a
с RecordEditFragment
, переходя на RecordListFragment
- Перед тем, как список получит возможность обновить, пользователь повторно вводит
RecordEditFragment
для Record a
RecordEditFragment
открывается со старыми данными - Фоновый поток выполняет сохранение
- Boom
Это классические условия гонки при асинхронной работе иЯ не могу себе представить, что это на самом деле лучший пракна Android, но я не могу найти документацию, которая утверждает, что иначе.Эти сценарии действительно возможны, или Android предотвращает подобные вещи?Почему бы просто не заблокировать пользовательский интерфейс для такой простой задачи, как вставка записи, чтобы не было возможности состязания?