Вы делаете два асинхронных вызова: один для удаления пользователей, а другой для их повторной вставки. Однако даже если вы сначала вызываете метод callDao.clean();
, а после этого вызываете callDao.insertInDB(list);
, не гарантируется, что операция clean()
будет выполнена до операции insertInDB()
(потому что именно так работают асинхронные вызовы).
Вот что происходит:
Вместо этого вам следует связывать асинхронные вызовы таким образом, чтобы второй вызывался, как только вы узнали, что первый уже завершен.
Как этого добиться, используя RxJava
и Completable
? Использование оператора andThen
, как указано в этом ответе
Вам следует изменить методы clean()
и insertInDB()
, чтобы они возвращали Completables
, использовать andThen
для их цепочки и затем подписаться.
Простой пример использования RxJava и andThen ()
FakeDatabase db = Room.databaseBuilder(this, FakeDatabase.class, "fake.db")
.fallbackToDestructiveMigration()
.build();
UserDao userDao = db.userDao();
User user1 = new User("Diego", "Garcia Lozano", "diegogarcialozano@fake.com");
User user2 = new User("Juan", "Perez", "juanperez@fake.com");
User user3 = new User("Pedro", "Lopez", "pedrolopez@fake.com");
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
Completable deleteAllCompletable = Completable.fromAction(userDao::deleteAll);
Completable insertUserCompletable = Completable.fromAction(() -> userDao.insertAll(users));
deleteAllCompletable
.andThen(Completable.fromAction(() -> System.out.println("Delete finished")))
.andThen(insertUserCompletable)
.andThen(Completable.fromAction(() -> System.out.println("Insert finished")))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();
Проверяя Logcat
после выполнения, вы можете видеть, что операции были выполнены в правильном порядке:
2018-11-19 16:07:02.056 10029-10047/? I/System.out: Delete finished
2018-11-19 16:07:02.060 10029-10047/? I/System.out: Insert finished
После этого Я проверил содержимое базы данных с помощью инструмента Браузер SQLite и увидел, что вставка работает правильно.
Использование @Transaction в DAO
Вы можете получить лучшее решение для вашей проблемы, не используя RxJava
. Вместо этого вы можете определить Transaction
в своем DAO, используя аннотацию @ Transaction , , как описано в этом посте . Это будет выглядеть примерно так:
ДАО
@Dao
public abstract class UserDao {
@Transaction
public void deleteAndCreate(List<User> users) {
deleteAll();
insertAll(users);
}
@Query("DELETE FROM User")
public abstract void deleteAll();
@Insert
public abstract void insertAll(List<User> users);
}
Активность
Completable.fromAction(() -> userDao.deleteAndCreate(users))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();
Проверка таблицы
Лично я бы сделал это с аннотацией @Transaction
.