Search code examples
androidasynchronousrealmrx-java

Realm: Creating Observable from asynchronous Transaction


In my Android app, I am using Realm and RxJava, and I want to update an Object by passing a new value. I use realm.executeTransactionAsync() for that. But I would like to subscribe to this event to do error handling in the class where I use this method. What I have done so far is this:

public Observable updateDogAge(final String dogId, final int age) {
    return Observable.create(new Observable.OnSubscribe<Dog>() {
        @Override
        public void call(final Subscriber<? super Dog> subscriber) {
            realm.executeTransactionAsync(realm1 -> realm1.where(Dog.class)
                            .equalTo(DOG_ID_FIELD, dogId)
                            .findFirst()
                            .setAge(age),
                    subscriber::onCompleted,
                    subscriber::onError);
        }
    });
}

Now I would like to get a boolean flag of whether or not updating this object was successful. Right now I feel like just calling subscriber::onCompleted is not the right solution. I am also not sure about the use of Observable.onCreate().

Can you tell me what is the right way to get an Observable (or Single) from an asynchronous Realm transaction?


Solution

  • I'd recommend creating your own "asynchronous" transaction for RxJava support.

    public Observable updateDogAge(final String dogId, final int age) {
        return Observable.defer(() -> {
            try(Realm r = Realm.getDefaultInstance()) {
                r.executeTransaction((realm) -> realm.where(Dog.class)
                            .equalTo(DOG_ID_FIELD, dogId)
                            .findFirst()
                            .setAge(age));
                return Observable.just(true);
            } catch(Throwable e) {
                return Observable.error(e);
            }
        });
    }
    

    Note: my RxJava is a bit hazy, I don't use it regularly.


    And of course, you need to subscribe this on a scheduler that runs on background threads.

    updateDogAge(id, age).subscribeOn(Schedulers.io())./*...*/
    


    In fact, I think you can use Observable.fromCallable() instead:

    public Observable updateDogAge(final String dogId, final int age) {
        return Observable.fromCallable(() -> {
            try(Realm r = Realm.getDefaultInstance()) {
                r.executeTransaction((realm) -> realm.where(Dog.class)
                            .equalTo(DOG_ID_FIELD, dogId)
                            .findFirst()
                            .setAge(age));
                return true;
            }
        });
    }