Предположим, что у нас есть простой интерфейс DAO:
@Dao
interface MyDao {
@Delete
fun delete(entity: MyEntity): Completable
}
, и мы ожидаем от Room, что он сгенерирует функцию, которая возвращает Completable
.Выполнение этого Completable
должно удалить сущность из базы данных.
Теперь мы вызываем функцию delete
в основном потоке, но подписываемся на нее в фоновом потоке.
// Called in the main thread
myDao.delete(myEntity)
.subscribeOn(Schedulers.background())
.subscribe()
Проблема состоит в том, что этот вызов приводит к IllegalStateException
с таким сообщением:
Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
Интересно, что другие функции, такие как, например, select (возвращает Single<MyEntity>
), работают отлично, их можно создавать в главном потоке, ноони выполняются в фоновом потоке.Поэтому я посмотрел в сгенерированный класс, чтобы увидеть, какие функции предоставляют IllegalStateException
в реализации удаления:
public SupportSQLiteStatement acquire() {
assertNotMainThread();
return getStmt(mLock.compareAndSet(false, true));
}
Вопрос в том, является ли это ошибкой или я должен вызывать удаление по-другому, например: Completale.defer { myDao.delete(myEntity)) }
?
Редактировать
Если быть более точным: я использую пользовательский запрос для удаления ("DELETE FROM myentities WHERE id = :id
) и вот сгенерированный код:
@Override
public Completable deleteByIdInternal(final long id) {
final SupportSQLiteStatement _stmt = __preparedStmtOfDeleteByIdInternal.acquire();
int _argIndex = 1;
_stmt.bindLong(_argIndex, id);
return Completable.fromCallable(new Callable<Void>() {
@Override
public Void call() throws Exception {
__db.beginTransaction();
try {
_stmt.executeUpdateDelete();
__db.setTransactionSuccessful();
return null;
} finally {
__db.endTransaction();
__preparedStmtOfDeleteByIdInternal.release(_stmt);
}
}
});
}