2015-12-12 21 views
16

Sto ancora cercando RxJava e lo utilizzo per fare alcune cose di networking con Retrofit 2. Lo sto provando da un paio di giorni e così il codice sembra più leggibile ora ma si è imbattuto in un problema che non riesco a capire un modo per aggirare.RxJava si iscrive nuovamente all'evento dopo il ripristino dell'attività

Sto tentando di eseguire un accesso (che restituisce un token API) e quindi utilizzare questo token per recuperare alcuni dati iniziali tutti nella stessa catena in modo che l'output della catena sia il token + i dati. Per fare questo io chiamo il mio servizio API con un

apiClient 
    .login() 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .flatMap(token -> getData(token)) 
    .subscribe(new Subscrber<Bundle>() {...}); 

Questo sembrava a posto, ma ho anche voluto mostrare una barra di avanzamento durante l'avvio e l'arresto della catena. Così ho aggiunto un .doOnSubscribe() e un .doOnUnsubscribe() anche a questo. Tuttavia ho notato che dopo il cambiamento di orientamento il frammento che stavo cercando di nascondere la barra di avanzamento è sempre nullo.

Così ho cercato e mi sono imbattuto nel lib RxLifecycle che sembrava come se potesse essere d'aiuto e io ora .cache() e annullare l'iscrizione dalla catena di eventi. Ma non riesco a capire come iscriversi allo stesso evento di nuovo in onCreate() dopo questo? Penso che mi manchi qualcosa di abbastanza semplice e apprezzerei qualsiasi aiuto con questo.

+1

La cosa migliore che puoi fare è dividere la tua logica e implementare il pattern 'MVP'. Dopo di ciò la classe 'Presenter' (che idealmente dovrebbe essere singleton per ogni istanza di visualizzazione) gestirà tutto il networking e manterrà la ricostruzione di on view dopo la rotazione dello schermo. In realtà c'è una libreria abbastanza carina che permette di usare il pattern 'MVP' basato su rxJava https://github.com/konmik/nucleus (è molto piccolo). Anche se non vuoi usarlo, puoi farti un'idea di come possa essere implementato – Than

+0

hmm .. ok quindi suppongo di dover leggere su una buona implementazione MVP prima di scendere la rotta RxJava ... –

+1

'MVP' può rendere il tuo codice molto più chiaro e risolverà questo problema, ma forse non è la soluzione che stai cercando (non è così facile passare l'intera architettura delle app in MVP) (ecco perché non l'ho postato come risposta). Sono sicuro che c'è un modo per farlo senza 'MVP' usando la lib di terze parti o alcuni buoni schemi ma non ho avuto alcuna soluzione pulita. Tratta il mio commento sopra come "come gli altri stanno affrontando un problema simile". – Than

risposta

0

È necessario fare in modo che si sottoscrive il stesso Osservabile esempio che viene restituito dal .cache(). In genere si memorizza questa istanza da qualche parte in un Singleton (come la classe Application), un frammento conservato o un servizio Android.

+0

Attenzione però, dato che cache() memorizza anche gli errori! – scana

1

Non è necessario utilizzare alcun modello di architettura per ottenerlo. Sebbene qualsiasi MVP/MVC sia bello per questioni di separazione, test, ecc., Rendendo il tuo Controller/Presentatore/DAO un singleton a livello di applicazione, che mantiene la memoria durante tutta la vita dell'applicazione, non è esattamente una buona idea.

Ecco un progetto di esempio utilizzando esempio frammento conservato e RxJava - https://github.com/krpiotrek/RetainFragmentSample

L'idea principale non è quella di utilizzare Frammento con setRetainInstance (vero) chiamati, che lo protegge dalla distruzione sul cambiamento di orientamento, e memorizzare la vostra Osservabile in là. Ecco come gestire che in Attività/Frammento onCreate

protected void onCreate(Bundle savedInstanceState) { 
    if (savedInstanceState == null) { 
     // first run, create observable 
     mInfoObservable = createInfoObservable(); 
     // set Observable in retained fragment 
     RetainFragmentHelper.setObject(this, getSupportFragmentManager(), mInfoObservable); 
    } else { 
     // following runs, get observable from retained fragment 
     mInfoObservable = RetainFragmentHelper.getObjectOrNull(this, getSupportFragmentManager()); 
    } 

    // subscribe 
    mInfoObservable.subscribe(...); 
} 

Tenete a mente che il vostro Observable deve memorizzare nella cache ultimo valore, un modo è quello uso della cache() dell'operatore.