2016-11-23 2 views
0

In meiner Android-App verwende ich Realm und RxJava, und ich möchte ein Objekt aktualisieren, indem ich einen neuen Wert übergebe. Ich benutze dafür realm.executeTransactionAsync(). Aber ich möchte dieses Ereignis abonnieren, um die Fehlerbehandlung in der Klasse durchzuführen, in der ich diese Methode verwende. Was ich bisher getan haben, ist dies:Realm: Observable aus asynchroner Transaktion erstellen

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

Nun würde Ich mag eine boolean Flagge erhalten, ob oder nicht aktualisiert diese Aufgabe erfolgreich war. Im Moment habe ich das Gefühl, nur subscriber::onCompleted anrufen ist nicht die richtige Lösung. Ich bin mir auch nicht sicher über die Verwendung von Observable.onCreate().

Können Sie mir sagen, was ist der richtige Weg, um eine Observable (oder Single) von einer asynchronen Realm-Transaktion zu bekommen?

Antwort

2

Ich würde empfehlen erstellen Sie Ihre eigenen "asynchronen" Transaktion für RxJava Unterstützung.

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

Hinweis: mein RxJava ein bisschen trüb ist, ich es nicht regelmäßig verwenden.


Und natürlich müssen Sie dies auf einem Scheduler abonnieren, der auf Hintergrundthreads läuft.

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


In der Tat, ich glaube, Sie Observable.fromCallable() stattdessen verwenden können:

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; 
     } 
    }); 
} 
+0

eingewickelt ist Das sieht gut aus und einfach, aber die Try-Catch ist nicht fangen der Throwable in der Transaktion. Irgendein Vorschlag dafür? – Terry

+0

Was meinst du mit "den Werfbaren in der Transaktion"? Die 'executeTransaction()' bricht die Transaktion bei Exception bereits ab, dafür ist sie zuständig. – EpicPandaForce

+0

Ich habe versucht, es mit 'executeTransactionAsync' zu verwenden. Mit synchroner Transaktion funktioniert es. – Terry

0

In Fall, wenn der Vorgang erfolgreich abgeschlossen wird, müssen Sie wahr, und wenn Fehler auftreten, müssen Sie falsch, richtig? Versuchen Sie immer true zurückzugeben und fügen Sie .onnErrorReturn hinzu und geben Sie false zurück. Sie können eine asynchrone Transaktion selbst durchführen, indem Sie die Methoden .subscribeOn() und .observeOn() und die synchrone Realmtransaktion verwenden. Aber indem Sie dies tun, müssen Sie die Realm-Instanz jedes Mal abrufen und freigeben, da sie Thread-abhängig ist. Dies wird ein wenig einfacher, da Sie abhängig vom Erfolg des Vorgangs True und False zurückgeben.

+0

Danke, das hört sich gut an. Können Sie mir ein Codebeispiel dafür zeigen? – Terry

+0

das ist, was in der Antwort unten in .subscribeOn (Schedulers.io) .observeOn (AndroidSchedulers.mainThread()) –

+0

und mit .onErrorReturn (false) -Operator –

0

Sie könnten auch Folgendes tun, um executeTransactionAsync anstelle von einfachen executeTransaction zu verwenden:

return Observable.fromEmitter(emitter -> { 
    try (Realm realm = Realm.getDefaultInstance()) { 
     realm.executeTransactionAsync(bgRealm -> { 
      bgRealm.where(Dog.class) 
        .equalTo(DOG_ID_FIELD, dogId) 
        .findFirst() 
        .setAge(age)); 
      emitter.onNext(true); 
     }); 
    } catch (Exception e) { 
     emitter.onError(e); 
    } 
}, Emitter.BackpressureMode.BUFFER); 

Auf diese Weise werden alle Ihre Realm-Transaktionen asynchron sein und Sie werden alle Warnungen über "Mischen asynchrone Abfragen mit lokalen schreibt ...".

Ein möglicher Nachteil dieses Ansatzes ist, dass fromEmitter nur in späteren Versionen von RxJava 1.x funktioniert und zu diesem Zeitpunkt noch experimentell ist (RxJava 1.2.3). Nicht sicher, ob es einen gleichwertigen Ansatz für RxJava 2 gibt.

Verwandte Themen