我将RxJava2与Room SQLite一起使用。我的DAO:
@Dao
public interface HeroDao {
@Insert
long create(Hero hero);
}
这就是我在RxJava2中使用它的方式:
Observable.just((int) heroDao.create(hero))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(id -> /** do stuff **/);
但是当我运行应用程序时,我在Logcat中遇到的错误是Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
我已经尝试将.allowMainThreadQueries()
附加到数据库构建器并且插入经过以确认我的正确性观察到的。看来LiveData和AsyncTasks是我可以尝试的其他方法,但是当我已经对RxJava2进行了大量投资时,我宁愿不去那里。
那么为什么我会收到这个错误?是不是subscribeOn(Schedulers.io())
足以卸载主线程的工作?否则我该怎么做?将Room查询转换为我遗漏的可观察量似乎有一些微妙之处?
答案 0 :(得分:5)
这是因为您使用了Observable.just
。此方法只是将对象包装到Observable
中,因此它在实际订阅之前创建,并在主线程上调用heroDao.create(hero)
。您应该使用Observable.fromCallable()
,或者更喜欢Single.fromCallable
。
您也可以在DAO中定义方法,如@Insert Single<Int> create(Hero hero);
有些链接可能会有所帮助:
Doing queries in Room with RxJava
7 Pro-tips for Room
答案 1 :(得分:1)
@Dmitry Ikryanov的回答是正确的,但是
您也可以使用defer()
createQuery().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(intger -> {
//do sth with intege
Thread.currentThread().getName());
},
Throwable::printStackTrace
);
}
public Observable<Integer> createQuery() {
return Observable.defer(() -> {
try {
return Observable.just((Integer) heroDao.create(hero));
} catch (Exception e) {
return Observable.error(e);
}
});
}