#android #rx-java2 #android-room
#Android #rx-java2 #android-room
Вопрос:
Предположим, что существует Dao
класс со следующими двумя методами:
1)
delete(items: List<Item>): Completable
2)
insert(items: List< Item >): Single<List<Long>>
Как я могу объединить их в @transaction
метод в Dao
классе, начиная с «метода удаления», а затем возвращая результат ‘метода вставки’?
Я хочу иметь метод с подписью, подобной этой:
@Transaction
fun deleteAndInsert(): Single<List<Long> > {
...
}
Ответ №1:
Я предполагаю, что ваша главная цель — иметь возвращаемый тип deleteAndInsert()
as Single
.
Вы можете добиться этого с небольшими изменениями
- сначала, сделав
delete()
иinsert()
функции синхронными. - Поскольку
@Transaction
работает только синхронно, нам нужно создать другую функцию, которая вызывает обаdelete()
иinsert()
. Кроме того, прокомментируйте эту функцию с@Transaction
- Создайте другую новую функцию, которая создает
Single
и вызывает вышеупомянутую функцию.
abstract class SampleDao{
protected abstract fun delete()
protected abstract fun insert(items: List<Item>) : List<Long>
@Transaction
protected open fun deleteAndInsertSync(items: List<Item>): List<Long>{
delete()
return insert(items)
}
fun deleteAndInsert(items:List<Item>): Single<List<Long>>{
return Single.create {
it.onSuccess(deleteAndInsertSync(items))
}
}
}
Ответ №2:
Я не думаю, что это возможно.
Я однажды попробовал это, и я получил ошибку времени компиляции, в которой говорилось:
«Метод, помеченный @Transaction, не должен возвращать отложенный / асинхронный тип возврата io.reactivex.Одиночный. Поскольку транзакции ограничены потоком, и Room не может гарантировать, что все запросы в реализации метода выполняются в одном потоке, разрешены только методы, реализованные синхронно @Transaction. Если транзакция запущена и выполняется смена потока и ожидается, то может возникнуть взаимоблокировка базы данных, если дополнительный поток попытается выполнить запрос. Это ограничение предотвращает возникновение такой ситуации.»
Ответ №3:
- Метод, помеченный @Transaction, не должен возвращать отложенный / асинхронный тип возврата io.reactivex.Одиночный. Поскольку транзакции ограничены потоком, и Room не может гарантировать, что все запросы в реализации метода выполняются в одном потоке, разрешены только методы, реализованные синхронно @Transaction. Если транзакция запущена и выполняется смена потока и ожидается, то может возникнуть взаимоблокировка базы данных, если дополнительный поток попытается выполнить запрос. Это ограничение предотвращает возникновение такой ситуации.
-
Когда я декомпилирую код в java, я вижу.
public interface CustomerDao { @Transaction @NotNull List deleteAndCreate(@NotNull List var1); @Query("DELETE FROM customer") @NotNull Completable deleteAll(); @Insert @NotNull List insertAll(@NotNull List var1); @Metadata( mv = {1, 1, 15}, bv = {1, 0, 3}, k = 3 ) public static final class DefaultImpls { @Transaction @NotNull public static List deleteAndCreate(CustomerDao $this, @NotNull List users) { Intrinsics.checkParameterIsNotNull(users, "users"); $this.deleteAll(); return $this.insertAll(users); } } }
Ответ №4:
Получить идентификаторы новых данных
затем удалите все элементы, которых нет в новых данных
@Query("DELETE FROM product WHERE id NOT IN(:idsNewItems)")
@Override
public abstract void deleteOldItems(List<String> idsNewItems)
;
Ответ №5:
Если вы delete
и insert
методы отмечены аннотацией, они выполняются в транзакции. Итак, в принципе, вам не нужно помечать свой deleteAndInsert
метод этой аннотацией. Итак, чем:
fun deleteAndInsert(items: List< Item >): Single<List<Long>> {
return delete().andThan(insert(items))
}
Комментарии:
1. Я не думаю, что тогда они будут выполнены в одной транзакции.