Использование RxJava и Okhttp

Я хочу запросить URL-адрес, используя okhttp в другом потоке (например, поток IO) и получить Response в главном потоке Android, но я не знаю, как создать Observable .

Solutions Collecting From Web of "Использование RxJava и Okhttp"

Сначала добавьте RxAndroid в свои зависимости, а затем создайте свой Observable следующим образом:

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

Он запросит ваш url в другом потоке (io thread) и будет наблюдать за ним в основной нити Android.

И, наконец, когда вы покидаете экран, используйте subsribtion.unsubscribe() чтобы избежать утечки памяти.

Когда вы используете Observable.create , вы должны написать много кода шаблона, также вы должны обрабатывать подписку самостоятельно. Лучшей альтернативой является использование отсрочки . Форма документа:

Не создавайте Observable до тех пор, пока наблюдатель не будет подписаться, и создайте новый наблюдаемый для каждого наблюдателя

Оператор Defer ждет, пока наблюдатель не присоединится к нему, и затем он генерирует Observable, как правило, с заводской функцией Observable. Он делает это заново для каждого абонента, поэтому, хотя каждый абонент может подумать, что он подписывается на тот же Observable, фактически каждый абонент получает свою собственную индивидуальную последовательность.

Так, как заметил Марцин Козиньский , вам просто нужно сделать это:

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

Легче и безопаснее использовать Observable.defer() вместо 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); } } }); 

Таким образом, вы можете отказаться от подписки и противодавления. Вот отличный пост Дэн Лью о create() и defer() .

Если вы хотите пройти маршрут Observable.create() он должен больше походить на эту библиотеку с isUnsubscribed() посыпаются повсюду. И я считаю, что это все еще не справляется с противодавлением.

Я понимаю, что этот пост немного стар, но есть новый и более удобный способ сделать это сейчас

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