2015-09-21 13 views
17

Desidero richiedere un URL utilizzando okhttp in un altro thread (come il thread IO) e ottenere Response nella thread principale di Android, ma non so come creare un Observable.Utilizzo di RxJava e Okhttp

risposta

19

Prima aggiungere RxAndroid alle vostre dipendenze, quindi creare il Observable in questo modo:

Subscription subscription = Observable.create(new Observable.OnSubscribe<Response>() { 
     OkHttpClient client = new OkHttpClient(); 
      @Override 
      public void call(Subscriber<? super Response> subscriber) { 
      try { 
       Response response = client.newCall(new Request.Builder().url("your url").build()).execute(); 
       if (response.isSuccessful()) { 
        if(!subscriber.isUnsubscribed()){ 
        subscriber.onNext(response); 
        } 
        subscriber.onCompleted(); 
       } else if (!response.isSuccessful() && !subscriber.isUnsubscribed()) { 
        subscriber.onError(new Exception("error")); 
       } 
      } catch (IOException e) { 
       if (!subscriber.isUnsubscribed()) { 
        subscriber.onError(e); 
       } 
      } 
      } 
     }) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Subscriber<Response>() { 
       @Override 
       public void onCompleted() { 

       } 

       @Override 
       public void onError(Throwable e) { 

       } 

       @Override 
       public void onNext(Response response) { 

       } 
      }); 

Sarà richiedere l'URL in un altro thread (io filo) ed osservare sul thread principale Android.

Infine, quando si esce dallo schermo, utilizzare subsribtion.unsubscribe() per evitare perdite di memoria.

Quando si utilizza Observable.create, si dovrebbe scrivere molto codice di codice, inoltre è necessario gestire l'abbonamento da soli. Un'alternativa migliore è usare defer. Formare il doc:

non creano osservabile fino sottoscritti osservatori, e creare una nuova osservabili per ogni osservatore

I Posticipa attese operatore fino a quando un osservatore sottoscrive, e poi genera una funzione Osservabile, tipicamente con una fabbrica osservabile . Lo fa di nuovo per ogni abbonato, quindi anche se ogni sottoscrittore di può pensare di iscriversi allo stesso Osservabile, in effetti ogni iscritto ottiene la propria sequenza individuale.

Così come Marcin Koziński detto, non vi resta che fare questo:

final OkHttpClient client = new OkHttpClient(); 
Observable.defer(new Func0<Observable<Response>>() { 
    @Override public Observable<Response> call() { 
     try { 
      Response response = client.newCall(new Request.Builder().url("your url").build()).execute(); 
      return Observable.just(response); 
     } catch (IOException e) { 
      return Observable.error(e); 
     } 
    } 
}); 
+0

Oltre alla risposta accettato da Saeed, si farebbe desidera annullare l'iscrizione dall'abbonamento per evitare perdite di memoria. Fonte: http://stackoverflow.com/a/34150022/1536976 da http://stackoverflow.com/users/3972175/esoxjem – Trilarion

+0

@Trilarion il tuo link sembra reindirizzare a questa stessa pagina (in modo ricorsivo!) –

+0

@VickyChijwani You ' Hai ragione. Anche se guardi il link, mi sembra di fare riferimento a un'altra domanda che non esiste più (i link a questa pagina e il mio link non sono gli stessi). Non so cosa sta succedendo qui e non ricordo di cosa si trattasse. Probabilmente qualcosa è stato cancellato da qualche parte nel frattempo. – Trilarion

16

E 'più facile e sicuro da usare Observable.defer() invece di Observable.create():

final OkHttpClient client = new OkHttpClient(); 
Observable.defer(new Func0<Observable<Response>>() { 
    @Override public Observable<Response> call() { 
     try { 
      Response response = client.newCall(new Request.Builder().url("your url").build()).execute(); 
      return Observable.just(response); 
     } catch (IOException e) { 
      return Observable.error(e); 
     } 
    } 
}); 

Che disiscrizione modo e contropressione sono gestite per te. Ecco a great post by Dan Lew su create() e defer().

Se si desidera percorrere il percorso Observable.create(), dovrebbe apparire più simile a this library con chiamate isUnsubscribed() sparse ovunque. E credo che questo ancora non gestisca la contropressione.

5

Mi rendo conto che questo post è un po 'vecchio, ma c'è un modo nuovo e più conveniente di fare questo ora

Observable.fromCallable { 
     client.newCall(Request.Builder().url("your url").build()).execute() 
    } 

Maggiori informazioni: https://artemzin.com/blog/rxjava-defer-execution-of-function-via-fromcallable/

+0

Potrebbe chiarire il codice? A 'new' manca prima di' Request', e dopo si genera un errore –

+2

Questo non è Java, è Kotlin – feresr

+0

Ops ... perso questo, mi spiace –