Terry Terry - 6 days ago 5
Android Question

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?

Answer

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;
        }
    });
}
Comments