2016-06-09 35 views
6

Ho il fuoco e dimentico le operazioni che non richiedono molto tempo, ma abbastanza a lungo che ho voluto eseguirle in sottofondo in modo reattivo. Il tempo di vita è fondamentalmente mentre la connessione al server esiste o sono trascorsi 10 secondi. Non so come conservarli in modo da poterli pulire in modo efficiente pur mantenendo il corretto ciclo di vita.Come ripulire l'incendio RxJava e dimenticare le iscrizioni?

Subscription fireAndForget = service.doSomething() 
            .timeout(10, TimeUnit.SECONDS) 
            .subscribe(() -> { 
             otherService.doAction() 
            }, (e) -> { Log.e("error", e) }); 
// what do I do with fireAndForget??? 

// If I use a CompositeSubscription 
subscriptions.add(fireAndForget) // how does it get removed???? 

potevo avere un CompositeSubscription sul mio collegamento che mantengono tiene di loro, ma poi come faccio a cancellare quando l'operazione è terminata? Dovrei anche prendermi la briga di cancellare una CompositeSubscription quando la sottoscrizione si disiscrive? Sono relativamente nuovo a Rx quindi non sono sicuro se sto solo cercando di fare qualcosa che Rx non avrebbe dovuto fare.

risposta

4

Suggerimento: Fuoco e dimenticare

Non state dimenticando se si mantiene un abbonamento intorno. Basta chiamare iscriviti e andare avanti.

service.doSomething() 
    .timeout(10, TimeUnit.SECONDS) 
    .subscribe(() -> { 
     otherService.doAction() 
    } 

Edit: garbage collection.

A meno che non si faccia qualcosa di molto strano (ad esempio utilizzando WeakReference), il codice di esecuzione in doSomething impedirà l'intera raccolta della garbage collection.

Pensa a RxJava come una cipolla, ogni volta che trasformi un osservabile (mappa, doOnNext, ecc.) Viene creato un nuovo Osservabile che avvolge il vecchio osservabile come una cipolla.

Per ogni trasformazione viene creato un nuovo Subscriber che passa i callback (onNext, onCompleted, onError) al successivo Subscriber nella catena.

Il motivo principale per un Subscription è così che è possibile chiamare unsubscribe. Ci sono due motivi per cui potresti voler annullare l'iscrizione.

  1. Hai un osservabile caldo. Fondamentalmente questo osservabile emetterà valori per sempre. Un esempio potrebbe essere un osservabile che emette il tempo ogni 30 secondi. Puoi chiamare unsubscribe quando non sei più interessato al valore del tempo.

  2. Si desidera annullare un'operazione lunga. Diciamo che stai caricando una pagina web da visualizzare all'utente, se l'utente preme indietro, vuoi annullare il caricamento (non ti interessa più dei risultati).

Esempio codice sorgente per il funzionamento mappa

Mappa semplicemente chiamate lift con una OperatorMap come argomento. Lift crea un nuovo Observable basato su un Operator, può essere ignorato per il momento.

public final <R> Observable<R> map(Func1<? super T, ? extends R> func) { 
    return lift(new OperatorMap<T, R>(func)); 
} 

OperatorMap crea un nuovo Subscriber che passa per lo più solo chiamate in qualunque Subscriber è dato.Questo potrebbe essere il Subscriber si passa in subscribe o un Subscriber creato da un'altra trasformazione map, non importa.

public final class OperatorMap<T, R> implements Operator<R, T> { 

    private final Func1<? super T, ? extends R> transformer; 

    public OperatorMap(Func1<? super T, ? extends R> transformer) { 
     this.transformer = transformer; 
    } 

    @Override 
    public Subscriber<? super T> call(final Subscriber<? super R> o) { 
     return new Subscriber<T>(o) { 

      @Override 
      public void onCompleted() { 
       o.onCompleted(); 
      } 

      @Override 
      public void onError(Throwable e) { 
       o.onError(e); 
      } 

      @Override 
      public void onNext(T t) { 
       try { 
        o.onNext(transformer.call(t)); 
       } catch (Throwable e) { 
        Exceptions.throwOrReport(e, this, t); 
       } 
      } 

     }; 
    } 

} 
+1

Oh ... Sembra facile, ma sono confuso. Cosa impedisce all'intera catena di oggetti di raccogliere i rifiuti? – Buttink

+0

In breve, il codice di esecuzione in 'doSomething' vede la mia risposta aggiornata per maggiori dettagli. – cyroxis

+0

Ciò che impedisce all'intera catena di oggetti di ottenere la garbage collection è il 'Subscription' che si sta tenendo. (come ha detto Cyroxis: "Non ti stai dimenticando di tenere un abbonamento in giro.") Senza il 'Subscription', i dati diventano irraggiungibili (non è collegato ad altri dati) e vengono raccolti. –

0

tuo CompositeSubscription devono essere conservati in qualsiasi oggetto padre di vostro gradimento. Ciò collegherà il ciclo di vita del genitore dello CompositeSubscription allo CompositeSubscription stesso: Quando l'oggetto genitore diventa irraggiungibile, lo CompositeSubscription con l'oggetto genitore sarà entrambi raccolto automaticamente.

Inoltre, se la parent di CompositeSubscription ha metodi del ciclo di vita come onStop(), è possibile annullare l'iscrizione manualmente allo CompositeSubscription. Allo stesso modo, se disponi di un metodo del ciclo di vita disponibile come onStart() o onResume(), puoi iscriverti (di nuovo) lì.

This page potrebbe fornire ulteriori informazioni sulla garbage collection.

1

Dimenticati di ottenere l'abbonamento a meno che tu non voglia sapere se è ancora iscritto o meno. In base alla progettazione, Observable cancellerà l'osservatore su Completato. Quindi poiché l'istanza non viene più utilizzata, il GC a un certo punto lo rimuoverà.

basta refactoring del codice:

service.doSomething().timeout(10, TimeUnit.SECONDS) 
           .subscribe(() -> { 
            otherService.doAction() 
           }, (e) -> { Log.e("error", e) }); 

Potete vedere alcuni esempi su come iscriversi lavora qui.

https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/creating/ObservableSubscription.java