Room-插入新值后执行删除

时间:2018-11-16 19:49:03

标签: android kotlin rx-java2 android-room

我正在研究Rxjava2,并且试图将Room Library与Rxjava2集成。问题是:我有一个填充的表,每次登录该应用程序时,都需要删除该表,然后在数据库中插入新内容。另外,删除和插入工作正常,但是当我尝试删除表内容后尝试插入新值时,delete方法将删除所有新值。(代码的某些部分在kotlin中,而其他部分在Java中) /> 我已经尝试过:RxJava2 + Room: data is not being inserted in DB after clearAllTables() call,但没有成功。.

DAO

@Dao
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(list:List<Something>)

@Query("DELETE FROM SomethingTable")
fun delete()

@Query("SELECT * FROM SomethingTable")
fun getAll(): Flowable<List<Something>>

我的类调用了DAO(CallDao)

//insert
fun insertInDB(list: List<Something>) {
    Completable.fromAction {
        dbDAO!!.insert(list)
    }.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe()
}

//delete
fun clean() {
    Completable.fromAction {
        dbDAO!!.delete()
    }.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.single())
            .subscribe()
}

//search all
fun findAll(): Observable<List<Something>>? {
    return Observable.create { subscriber ->
        dbDAO!!.getAll()
                .subscribeOn(Schedulers.io())
                .subscribe {it->
                    subscriber.onNext(it)
                }
    }
}

当我单击登录按钮时调用的方法

private void clearAndInsertInDB() {
CallDao callDao= new CallDao(getActivity());
//delete all table values
callDao.clean();

Something sm = new Something("test1", "test2");
ArrayList<Something> list = new ArrayList<>();
list.add(sm);
list.add(sm);
//insert new values
callDao.insertInDB(list);

//get all new values in DB
callDao.findAll()
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(res -> {
      //here gives me a IndexOutOfBoundsException
      Log.d("logDebug", res.get(0).getCodeExemple());
    });
}

也欢迎在我的代码中进行任何更正:),但是主要问题是delete方法删除所有新的插入值,并且应该只删除旧的值。

2 个答案:

答案 0 :(得分:5)

您要进行两个异步调用:一个删除用户,另一个插入用户。但是,即使您先调用callDao.clean();方法,然后再调用callDao.insertInDB(list);,也不能保证在插入操作之前执行clean操作(因为这是异步调用的工作方式)。 / p>

正在发生的事情:

Async calls without waiting

相反,您应该将异步调用链接起来,以使第二个调用在知道第一个已经完成后立即得到调用。

Chained async calls

如何使用RxJava实现这一目标?按照in this answer

使用andThen运算符

您应该修改cleaninsert方法以返回Completable,使用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

然后I checked the content of the database使用工具SQLite Browser,发现插入片段正常工作。

SqliteBrowser showing the proper data in the table

在DAO中使用@Transaction

您可以完全不用RxJava来获得更好的解决方案。相反,您可以使用'@Transaction'注释as explained in this post在DAO中定义一个事务。看起来像这样:

Dao

@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();

检查表格

Table using @Transcation

我个人会使用@Transaction注释。

答案 1 :(得分:0)

那么,按下按钮后,您还有剩余值吗? 我尚无法发表评论,所以我在这里问,对此感到抱歉