Reputation: 91
I'm trying to make a call to my contentResolver that accesses my sql DB in a reactive way. I know sqlBrite exists, but I have to use sqLite. I'm new to rxJava(2) and somehow stitched together 3 calls that all work as expected magically. I don't know which one to use. I'm using rxJava2 and some of the articles I read that brought me to this point seemed old. What's the preferred way to accomplish this? I'm also not using retroLambda...baby steps for me(I'll admit, it does make things look really nice though).
This is the starting call and subscribe function:
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");
}
};
}
These are the three RxJava functions that for now query my DB:
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;
}
Upvotes: 2
Views: 482
Reputation: 11058
Observable.fromCallable
is the best choice here because it just fits your needs: execute some code and return a value. defer
and create
are meant for more complex cases such as wrapping callbacks or manipulating the lifecycle of the stream.
Tip: since you are using a Cursor
, I think a better design solution would be to emit exact data from your data source (instead of cursor itself) and close the cursor onsite:
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 is just a reactive wrapper around SQLite.
Upvotes: 1