2016-06-11 8 views
2

Was ist der beste Weg, um neue Objekte automatisch von einer Observablen abzurufen, wenn Sie ein externes Ereignis haben, das Ihnen sagt, dass Sie dies tun sollten?Automatisches Abrufen von Objekten aus beobachtbaren Objekten, wenn ein Ereignis ohne Ereignisbus ausgelöst wird

Zum Beispiel kann sagen, ich habe und ItemRepository, die eine getAllItems() Methode implementiert (die Observable<List<Item>> von einem Webservice zurückgibt), und dann ein externes Ereignis (wie eine Push-Benachrichtigung) erzählt meine Anwendung, die die Daten aktualisiert werden muss. (Auch die ItemRepository in einem Presenter verwendet und dass Moderator genannt hat die getAllItems und es onNext ist, ist es Daten s aktualisiert.)

Ich weiß, das leicht mit Eventbus getan werden kann (hören Sie für dieses Ereignis, wenn seine gefeuert , hole wieder), aber ich frage mich, ob es möglich ist, das komplett automatisch zu machen.

Danke.

bearbeiten

Dies ist eine Lösung, die ich mit aufkommen, mit Hilfe von SQLBrite Bibliothek, aber nicht sicher, ob es der beste oder sauberste Weg, es zu tun. wir haben eine PublishSubject, dass die Ereignisse zu gesendete:

PublishSubject<Object> updateEvent;

und in den getAllItems() -Methode, prüfen wir für die Ereignisse von diesem Thema:

public Observable<List<Item>> getAll() { 
    Observable.OnSubscribe<List<Item>> subscribe = subscriber -> { 
     updateEvent.subscribe(s -> { 
      subscriber.onNext(dbItemRepository.getAll()); 
     }); 
     subscriber.onNext(dbItemRepository.getAll());// for the first call 
    }; 
    final Observable<List<Item>> automatonObservable = Observable.create(subscribe) = 
      .onBackpressureLatest() 
      .observeOn(Schedulers.computation()) 
      .onBackpressureLatest(); 
    return automatonObservable; 
} 
+0

Rückrufe? LocalBoradcastManager? – tamtom

+0

@tamtom bitte über die Implementierung von Rückrufen in diesem Fall, danke. – Bobby

+0

Bitte, überprüfen Sie meine Antwort! –

Antwort

2

denke ich, Rodrigo Henriques die richtige Idee hat, aber wir brauchen sie ein wenig ändern, um Ihre Frage nach:

public static Observable<String> observeRepositoryUpdates(ItemsRepository repo, Observable<Void> updateTrigger) { 
    updateTrigger 
    //you can insert observeOn here 
    .flatMap(event -> repository.getAllItems()); 
} 

public static void doWork() { 
    ItemsRepository repo = new ItemsRepository(); 
    PublishSubject<Void> updateTrigger = PublishSubject.create(); 

    observeRepositoryUpdates(repo, updateTrigger) 
    .subscribe(items -> System.out.println(items.toString()); 

    updateTrigger.onNext(null);//trigger update 
} 

auf Ihr Event Je, es muss nicht ein PublishSubject, andere sein Observable kann das Repository-Update auslösen.

Wenn Ihr Ereignis häufig auftritt und Sie möchten, dass das bereits laufende Repository-Update gelöscht und neu gestartet wird, können Sie den Operator switchMap verwenden.

+0

Wenn Sie das Element vom Ereignis und vom ersten Aufruf erhalten möchten, können Sie verwenden: 'itemRepository.getAll(). mergeWith (itemUpdateEvent.flatMap (event -> itemRepository.getAll())); ' –

+0

In diesem Fall ist es besser,' concat' anstelle von 'mergeWith' zu verwenden, um sicher zu gehen, dass wir zuerst Elemente aus Repo holen und dann nur Update-Ereignisse beobachten. Weil 'concat' wartet, wenn die erste Sequenz abgeschlossen ist und dann die zweite Sequenz abonniert (während die Zusammenführung nicht auf den Abschluss der ersten Sequenz wartet). – marwinXXII

+0

Danke, diese Antwort mit der Kombination der Kommentare ist perfekt. – Bobby

0

Sie verwenden sollten, ein Thema.

Überprüfen Sie es.

public class ExampleUnitTest { 
    @Test 
    public void testSample() throws Exception { 
     ItemRepository itemRepository = new ItemRepository(); 

     itemRepository.getAllItems() 
       .doOnNext(items -> System.out.println("Initializing emission...")) 
       .flatMap(Observable::from) 
       .subscribe(System.out::println); 

     List<Item> items = new ArrayList<>(); 

     items.add(new Item("First")); 
     items.add(new Item("Second")); 

     itemRepository.publishNewItems(items); 

     items.add(new Item("Third")); 
     items.add(new Item("Fourth")); 

     itemRepository.publishNewItems(items); 
    } 

    public class ItemRepository { 
     private PublishSubject<List<Item>> itemsListSubject = PublishSubject.create(); 

     public Observable<List<Item>> getAllItems() { 
      return itemsListSubject; 
     } 

     public void publishNewItems(List<Item> items) { 
      itemsListSubject.onNext(items); 
     } 
    } 

    public class Item { 
     private String name; 

     public Item(String name) { 
      this.name = name; 
     } 

     @Override 
     public String toString() { 
      return "Item{" + 
        "name='" + name + '\'' + 
        '}'; 
     } 
    } 
} 

Der obige Code wird gedruckt:

Initializing emission... 
Item{name='First'} 
Item{name='Second'} 
Initializing emission... 
Item{name='First'} 
Item{name='Second'} 
Item{name='Third'} 
Item{name='Fourth'} 

Also, Sie haben eine beobachtbare, dass eine Artikelliste jederzeit emittieren, die Sie wollen.

Ich empfehle Ihnen, um die Betreff-Dokumentation here zu sehen.

Hoffe, dass es hilft.

Mit freundlichen Grüßen.

+0

danke für deine Info, aber das ist anders, weil du deine Daten generierst, aber im Falle meiner Frage wollen wir nur, dass 'getAllItems()' neue Elemente so schnell ausstrahlt, wie ein neues Event hereinkommt habe bereits eine Lösung mit 'PublishSubject' entwickelt, die das' getAllItems' (als das Ereignis) abhört und wenn ein Element von diesem Thema ausgegeben wird, erhält es die Elemente, aber ich denke nicht, dass das die beste Idee ist. – Bobby

+0

Ich habe meine Frage mit der Methode bearbeitet, bitte überprüfe sie, danke. – Bobby

+0

Buddy, ich habe diese Lösung in meinem Projekt verwendet, um das gleiche Ergebnis wie du zu erzielen. Ich glaube nicht, dass Sie meine Probe richtig bekommen. Solange Sie neue Dateninformationen erhalten, müssen Sie diese nur an Ihr veröffentlichtes Thema senden und er wird ihre Abonnenten aktualisieren. –