这三个 RX observables 都按预期工作......哪种方式最好?
These three RX observables all work as expected...which way is the best?
我正在尝试调用我的 contentResolver,它以反应方式访问我的 sql 数据库。我知道 sqlBrite 存在,但我必须使用 sqlite。我是 rxJava(2) 的新手,以某种方式将 3 个调用拼接在一起,所有这些调用都神奇地按预期工作。我不知道该用哪一个。我正在使用 rxJava2,我读到的一些让我走到这一步的文章似乎已经过时了。实现此目标的首选方法是什么?我也没有使用 retroLambda ......对我来说是婴儿步骤(我承认,它确实让事情看起来非常好)。
这是开始调用和订阅函数:
Observable<Cursor> dbObserver = mTmdbDatabaseService.getCursor1(123456);
dbObserver.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(testDBObserver());
private Observer<Cursor> testDBObserver() {
return new Observer<Cursor>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "testDBObserver.onSubscribe");
//Save the disposable to remove it later onDestroy
mCompositeDisposable.add(d);
}
@Override
public void onNext(Cursor c) {
int num = c.getCount();
Log.d(TAG, "testDBObserver.onNext: " + c.getCount());
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "testDBObserver.onError");
}
@Override
public void onComplete() {
Log.d(TAG, "testDBObserver.onComplete");
}
};
}
这些是现在查询我的数据库的三个 RxJava 函数:
public Observable getCursor1(final int value) {
Observable<Cursor> cursorObservable = Observable.fromCallable(new Callable<Cursor>() {
@Override
public Cursor call() throws Exception {
int id = value;
String stringId = Integer.toString(id);
Uri uri = MovieContract.MovieEntry.CONTENT_URI;
uri = uri.buildUpon().appendPath(stringId).build();
Cursor c = mContext.getContentResolver().query(uri,
null,
null,
null,
MovieContract.MovieEntry.COLUMN_MOVIE_ID);
return c;
}
});
return cursorObservable;
}
public Observable<Cursor> getCursor2(final int value) {
return Observable.defer(new Callable<ObservableSource<? extends Cursor>>() {
@Override
public ObservableSource<? extends Cursor> call() throws Exception {
int id = value;
String stringId = Integer.toString(id);
Uri uri = MovieContract.MovieEntry.CONTENT_URI;
uri = uri.buildUpon().appendPath(stringId).build();
Cursor c = mContext.getContentResolver().query(uri,
null,
null,
null,
MovieContract.MovieEntry.COLUMN_MOVIE_ID);
return Observable.just(c);
}
});
}
public Observable<Cursor> getCursor3(final int value) {
Observable<Cursor> observable = Observable.create(new ObservableOnSubscribe<Cursor>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Cursor> subscriber) throws Exception {
int id = value;
String stringId = Integer.toString(id);
Uri uri = MovieContract.MovieEntry.CONTENT_URI;
uri = uri.buildUpon().appendPath(stringId).build();
Cursor c = mContext.getContentResolver().query(uri,
null,
null,
null,
MovieContract.MovieEntry.COLUMN_MOVIE_ID);
subscriber.onNext(c);
subscriber.onComplete();
}
});
return observable;
}
Observable.fromCallable
是这里的最佳选择,因为它正好符合您的需要:执行一些代码并 return 一个值。 defer
和 create
适用于更复杂的情况,例如包装回调或操纵流的生命周期。
提示:由于您使用的是 Cursor
,我认为更好的设计解决方案是从数据源(而不是游标本身)发出准确的数据并现场关闭光标:
Observable<Result> cursorObservable = Observable.fromCallable ... {
@Override
public Cursor call() throws Exception {
...
Cursor c = ...
Result result = ... //get your data from the cursor
c.close();
return result;
}
});
P.S。 SQLBrite 只是 SQLite 的反应式包装器。
我正在尝试调用我的 contentResolver,它以反应方式访问我的 sql 数据库。我知道 sqlBrite 存在,但我必须使用 sqlite。我是 rxJava(2) 的新手,以某种方式将 3 个调用拼接在一起,所有这些调用都神奇地按预期工作。我不知道该用哪一个。我正在使用 rxJava2,我读到的一些让我走到这一步的文章似乎已经过时了。实现此目标的首选方法是什么?我也没有使用 retroLambda ......对我来说是婴儿步骤(我承认,它确实让事情看起来非常好)。
这是开始调用和订阅函数:
Observable<Cursor> dbObserver = mTmdbDatabaseService.getCursor1(123456);
dbObserver.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(testDBObserver());
private Observer<Cursor> testDBObserver() {
return new Observer<Cursor>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "testDBObserver.onSubscribe");
//Save the disposable to remove it later onDestroy
mCompositeDisposable.add(d);
}
@Override
public void onNext(Cursor c) {
int num = c.getCount();
Log.d(TAG, "testDBObserver.onNext: " + c.getCount());
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "testDBObserver.onError");
}
@Override
public void onComplete() {
Log.d(TAG, "testDBObserver.onComplete");
}
};
}
这些是现在查询我的数据库的三个 RxJava 函数:
public Observable getCursor1(final int value) {
Observable<Cursor> cursorObservable = Observable.fromCallable(new Callable<Cursor>() {
@Override
public Cursor call() throws Exception {
int id = value;
String stringId = Integer.toString(id);
Uri uri = MovieContract.MovieEntry.CONTENT_URI;
uri = uri.buildUpon().appendPath(stringId).build();
Cursor c = mContext.getContentResolver().query(uri,
null,
null,
null,
MovieContract.MovieEntry.COLUMN_MOVIE_ID);
return c;
}
});
return cursorObservable;
}
public Observable<Cursor> getCursor2(final int value) {
return Observable.defer(new Callable<ObservableSource<? extends Cursor>>() {
@Override
public ObservableSource<? extends Cursor> call() throws Exception {
int id = value;
String stringId = Integer.toString(id);
Uri uri = MovieContract.MovieEntry.CONTENT_URI;
uri = uri.buildUpon().appendPath(stringId).build();
Cursor c = mContext.getContentResolver().query(uri,
null,
null,
null,
MovieContract.MovieEntry.COLUMN_MOVIE_ID);
return Observable.just(c);
}
});
}
public Observable<Cursor> getCursor3(final int value) {
Observable<Cursor> observable = Observable.create(new ObservableOnSubscribe<Cursor>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Cursor> subscriber) throws Exception {
int id = value;
String stringId = Integer.toString(id);
Uri uri = MovieContract.MovieEntry.CONTENT_URI;
uri = uri.buildUpon().appendPath(stringId).build();
Cursor c = mContext.getContentResolver().query(uri,
null,
null,
null,
MovieContract.MovieEntry.COLUMN_MOVIE_ID);
subscriber.onNext(c);
subscriber.onComplete();
}
});
return observable;
}
Observable.fromCallable
是这里的最佳选择,因为它正好符合您的需要:执行一些代码并 return 一个值。 defer
和 create
适用于更复杂的情况,例如包装回调或操纵流的生命周期。
提示:由于您使用的是 Cursor
,我认为更好的设计解决方案是从数据源(而不是游标本身)发出准确的数据并现场关闭光标:
Observable<Result> cursorObservable = Observable.fromCallable ... {
@Override
public Cursor call() throws Exception {
...
Cursor c = ...
Result result = ... //get your data from the cursor
c.close();
return result;
}
});
P.S。 SQLBrite 只是 SQLite 的反应式包装器。