'Android Room with RxJava handle empty query result

Trying to test new Android Room librarty with RxJava adapter. And I want to handle result if my query returns 0 objects from DB:

So here is DAO method:

@Query("SELECT * FROM auth_info")
fun getAuthInfo(): Flowable<AuthResponse>

And how I handle it:

database.authDao()
    .getAuthInfo()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .switchIfEmpty { Log.d(TAG, "IS EMPTY") }
    .firstOrError()
    .subscribe(
            { authResponse -> Log.d(TAG, authResponse.token) },
            { error -> Log.d(TAG, error.message) })

My DB is empty, so I expect .switchIfEmty() to work, but none of handling methods is firing. Neither .subscribe() nor .switchIfEmpty()



Solution 1:[1]

In version 1.0.0-alpha5, room added support of Maybe and Single to DAOs, so now you can write something like

@Query("SELECT * FROM auth_info")
fun getAuthInfo(): Maybe<AuthResponse>

You can read more about it here

Solution 2:[2]

switchIfEmpty takes as parameter a Publisher<AuthResponse>. Through SAM-conversion your given anonymous function is turned into this class. However it does not follow the behavior expected from a Publisher so it will not work as expected.

Replace it with a correct implementation like Flowable.empty().doOnSubscribe { Log.d(TAG, "IS EMPTY") } and it should work.

Solution 3:[3]

You could use some wrapper for result. For example:

public Single<QueryResult<Transaction>> getTransaction(long id) {
            return createSingle(() -> database.getTransactionDao().getTransaction(id))
                    .map(QueryResult::new);
}

    public class QueryResult<D> {
            public D data;
            public QueryResult() {}

            public QueryResult(D data) {
                this.data = data;
            }

            public boolean isEmpty(){
                return data != null;
            }
 }

protected <T> Single<T> createSingle(final Callable<T> func) {
            return Single.create(emitter -> {
                try {
                    T result = func.call();
                    emitter.onSuccess(result);

                } catch (Exception ex) {
                    Log.e("TAG", "Error of operation with db");
                }
            });
}

And use it like 'Single' in this case you will get result in any case. Use:

dbStorage.getTransaction(selectedCoin.getId())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(r -> {
                         if(!r.isEmpty()){
                           // we have some data from DB
                         } else {
                       }
                    })

Solution 4:[4]

Already solve, with this loopbreakcondition

mapping.append(         "<rowcheck offset=\"0\">");
        mapping.append(             "<cellcheck offset=\"0\"/>");
        mapping.append(         "</rowcheck>");
        mapping.append(     "</loopbreakcondition>");

This code line is for stop readeing when the next row, the cell of the offset is null, so with that line if the next row, the first cell is null it will stop reading

cellcheck offset=\"0\"/>");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 J-rooft
Solution 2 Kiskae
Solution 3
Solution 4 jvir