Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using RxJava and Okhttp

Tags:

I want to request to a url using okhttp in another thread (like IO thread) and get Response in the Android main thread, But I don't know how to create an Observable.

like image 300
Santos Black Avatar asked Sep 21 '15 05:09

Santos Black


People also ask

What is OkHttp used for?

What is OkHttp? OkHttp is an HTTP client from Square for Java and Android applications. It's designed to load resources faster and save bandwidth. OkHttp is widely used in open-source projects and is the backbone of libraries like Retrofit, Picasso, and many others.

Is RxJava deprecated?

RxJava, once the hottest framework in Android development, is dying. It's dying quietly, without drawing much attention to itself. RxJava's former fans and advocates moved on to new shiny things, so there is no one left to say a proper eulogy over this, once very popular, framework.

Why do we use OkHttp in Android?

OkHttp android provides an implementation of HttpURLConnection and Apache Client interfaces by working directly on a top of java Socket without using any extra dependencies.


2 Answers

First add RxAndroid to your dependencies, then create your Observable like this:

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

It will request your url in another thread (io thread) and observe it on android main thread.

And finally when you leave the screen use subsribtion.unsubscribe() to avoid memory leak.

When you use Observable.create, you should write a lot of boilerplate code, also you must handle subscription by your own. A better alternative is to use defer. Form the doc:

do not create the Observable until the observer subscribes, and create a fresh Observable for each observer

The Defer operator waits until an observer subscribes to it, and then it generates an Observable, typically with an Observable factory function. It does this afresh for each subscriber, so although each subscriber may think it is subscribing to the same Observable, in fact each subscriber gets its own individual sequence.

So as Marcin Koziński mentioned, you just need to do this:

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);         }     } }); 
like image 110
Saeed Masoumi Avatar answered Oct 25 '22 14:10

Saeed Masoumi


It's easier and safer to use Observable.defer() instead of 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);         }     } }); 

That way unsubscription and backpressure are handled for you. Here's a great post by Dan Lew about create() and defer().

If you wished to go the Observable.create() route then it should look more like in this library with isUnsubscribed() calls sprinkled everywhere. And I believe this still doesn't handle backpressure.

like image 36
Marcin Koziński Avatar answered Oct 25 '22 14:10

Marcin Koziński