2015-09-21 20 views
17

Chcę zażądać adresu URL za pomocą okhttp w innym wątku (jak wątek IO) i uzyskać Response w głównym wątku systemu Android, ale nie wiem, jak utworzyć Observable.Używanie RxJava i Okhttp

Odpowiedz

19

RxAndroid Pierwszy dodatek do uzależnień, a następnie utworzyć Observable takiego:

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) { 

       } 
      }); 

To zwróci url w innym wątku (IO gwintu) i obserwować go na Androidzie głównego wątku.

I na koniec, po wyjściu z ekranu, użyj subsribtion.unsubscribe(), aby uniknąć wycieku pamięci.

Podczas korzystania z Observable.create powinieneś napisać dużo kodu na płycie głównej, również musisz samodzielnie zarządzać subskrypcją. Lepszą alternatywą jest użycie defer. Postać doc:

nie tworzą się zaobserwować aż abonentów obserwatora, i tworzenia świeży zaobserwowania dla każdego obserwatora

The DEFER operator czeka do obserwatora zgadza się go, a następnie generuje Obserwowalne, zwykle z funkcją obserwowalną . Robi to ponownie dla każdego abonenta, więc chociaż każdy subskrybent może przypuszczać, że subskrybuje to samo Obserwowalne, w rzeczywistości każdy subskrybent otrzymuje swoją własną indywidualną sekwencję.

Więc jak Marcin Koziński wspomniano, po prostu trzeba to zrobić:

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

Oprócz przyjętej Odpowiedź Saeed, byś chcesz zrezygnować z subskrypcji, aby uniknąć wycieków pamięci. Źródło: http://stackoverflow.com/a/34150022/1536976 autor: http://stackoverflow.com/users/3972175/esoxjem – Trilarion

+0

@Trilarion twój link wydaje się przekierować na tę właśnie stronę (rekurencyjnie!) –

+0

@VickyChijwani You ' w porządku. Chociaż, jeśli spojrzysz na link, odniosę się do innego pytania, które już nie istnieje (linki do tej strony i mój link nie są takie same). Nie wiem, co się tutaj dzieje i nie pamiętam, o co chodzi. Prawdopodobnie coś zostało usunięte gdzieś w międzyczasie. – Trilarion

16

Łatwiej i bezpieczniej jest używać Observable.defer() zamiast 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); 
     } 
    } 
}); 

ten sposób wypisania i ciśnienie wsteczne są obsługiwane dla Ciebie. Oto a great post by Dan Lew około create() i defer().

Jeśli chcesz jechać na trasę Observable.create(), powinna ona wyglądać bardziej jak w this library z rozmowami isUnsubscribed() posypanymi wszędzie. I uważam, że nadal nie radzi sobie z przeciwciśnieniem.

5

Zdaję sobie sprawę, ten post jest trochę stary, ale jest nowy i bardziej wygodny sposób to zrobić teraz

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

Więcej informacji: https://artemzin.com/blog/rxjava-defer-execution-of-function-via-fromcallable/

+0

Czy możesz wyjaśnić kod? Brak 'nowego' przed' Żądaniem', a następnie zgłasza błąd –

+2

To nie jest Java, to jest Kotlin – feresr

+0

Ops ... przepuściło to, przepraszam –