这是我的查询
@Query("SELECT EXISTS(SELECT 1 FROM media2 WHERE path = :path AND isFav = 1 LIMIT 1)")
int checkIsFav(String path);
从存储库调用
public boolean checkIsFav(String path) {
return mDatabase.favDAO().checkIsFav(path) == 1;
}
这有时会导致以下错误
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
我明白为什么,但我需要一个返回才能确定项目是否为收藏。
我将RXjava用于其他数据库操作,但它们不需要返回。
Observable.fromCallable(() -> mDatabase.favDAO().checkIsFav(path) == 1);
或
Observable.just(mDatabase)
.subscribeOn(Schedulers.io())
.subscribe(db -> db.favDAO().insertMedia2(media));
我在片段中使用此方法
if (mediaViewModel.checkIsFav(media.getPath())){
mediaViewModel.removeFav(media.getPath());
} else {
media.setFav(true);
mediaViewModel.addFav(media);
}
和回收器适配器。
boolean isfav = ((App)context.getApplicationContext()).getRepository().checkIsFav(currentItem.getPath());
运行此查询时获取回调的最简单方法是什么?
更新了单一问题:
这是我在Dao中的查询
@Query("SELECT EXISTS(SELECT 1 FROM media2 WHERE path = :path AND isFav = 1 LIMIT 1)")
Single<Integer> checkIsFav(String path);
我在存储库中的方法
public Single<Integer> checkIsFav(String path){
return mDatabase.favDAO().checkIsFav(path);
}
我需要从我的适配器和我的片段进行此调用。如何调用它会是这样的?
((App)context.getApplicationContext()).getRepository().checkIsFav(media.getPath()).subscribeOn(
((App)context.getApplicationContext()).getRepository().checkIsFav(media.getPath()).subscribeOn(
Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(
new SingleObserver<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
});
这似乎并不合适。在我转换到房间之前,这是我的电话
if (App.favDB.existFav(currentItem.getPath()))
在我的SQLiteOpenHelper
中触发了这个 public boolean existFav(String path) {
SQLiteDatabase db = getReadableDatabase();
Cursor cur = db.rawQuery(
String.format("SELECT EXISTS(SELECT 1 FROM %s WHERE %s=? LIMIT 1)", TABLE_NAME, MEDIA_PATH),
new String[]{ path });
boolean tracked = cur.moveToFirst() && cur.getInt(0) == 1;
cur.close();
return tracked;
}
也许我没有正确思考这个问题。
我所要做的就是确定这张媒体是否存在于我的表格中。
答案 0 :(得分:2)
我认为你应该在主线程中观察你的数据。所以使用
observeOn(AndroidSchedulers.mainThread()).
尝试将其更改为
Observable.just(mDatabase)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(db -> db.favDAO().insertMedia2(media));
另见observeOn()
答案 1 :(得分:0)
尝试更改:
@Query("SELECT EXISTS(SELECT 1 FROM media2 WHERE path = :path AND isFav = 1 LIMIT 1)")
int checkIsFav(String path);
为:
@Query("SELECT EXISTS(SELECT 1 FROM media2 WHERE path = :path AND isFav = 1 LIMIT 1)")
Single<Integer> checkIsFav(String path);
使用RxJava with Room有效,但我没有尝试使用SELECT EXISTS
,所以YMMV。
答案 2 :(得分:0)
您应该添加到build.gradle
实施'android.arch.persistence.room:rxjava2:version'
关于每种类型的行为方式,请查看此媒体帖子https://medium.com/google-developers/room-rxjava-acb0cd4f3757
答案 3 :(得分:0)
呃,你以前总是在UI线程上读这个。现在Room默认强制执行,因为它可能会阻止UI线程。
如果您不想关心此限制并且只想让旧类型的代码正常工作,则可以使用RoomDatabase.Builder's allowMainThreadQueries()
否则,只需暴露Flowable并订阅Io,就像通常那样在Ui上观察。
答案 4 :(得分:0)
我们可以像这样创建Single:
public Single<SomeObject> getSomeObjectFromDB(Session session) {
return createAsyncSingle(() -> database.getSomeDao().getSomeObject())
.subscribeOn(Schedulers.io()) // We can move it on upper level;
}
其中:
protected <T> Single<T> createAsyncSingle(final Callable<T> func) {
return Single.create(emitter -> {
try {
T result = func.call();
if(result != null) {
emitter.onSuccess(result);
} else {
emitter.onError(new NullPointerException("Empty result from DB"));
}
} catch (Exception ex) {
Logger.e("TAG", "Error operation with DB");
}
});
}