RxJava1.x从入门到放弃再到RxJava 2.x(二)

前言

RxJava1.x从入门到放弃再到RxJava 2.x(一)
这篇文章讲解了最简单的入门,本节我们将会一起学习RxJava的线程调度。

正文

上一篇文章中开篇就讲到RxJava就是来处理异步任务的。但是默认情况下我们在哪个线程调用subscribe()就在哪个线程生产事件,在哪个线程生产事件就在哪个线程消费事件。那怎么做到异步呢?RxJava为我们提供Scheduler用来做线程调度,我们来看看RxJava提供了哪些Scheduler。

我们来看一段代码:

Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
        Log.d(TAG, "upstream's thread:"+Thread.currentThread().getName());
        emitter.onNext(1);
        emitter.onComplete();


    }
}).subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d(TAG, "downstream's thread:"+Thread.currentThread().getName());
            }
        });

运行后的log:

04-23 02:25:21.323 4135-4162/com.example.dawn4get.myapplication D/rx: upstream's thread:RxNewThreadScheduler-1

04-23 02:25:21.361 4135-4135/com.example.dawn4get.myapplication D/rx: downstream's thread:main

可以看到,上游在子线程发射数据源,下游在主线程接收。主要起作用的代码是:

subscribeOn(Schedulers.newThread())
observeOn(AndroidSchedulers.mainThread())

简单的来说, subscribeOn() 指定的是上游发送事件的线程, observeOn() 指定的是下游接收事件的线程.

多次指定上游的线程只有第一次指定的有效, 也就是说多次调用subscribeOn() 只有第一次的有效, 其余的会被忽略.

多次指定下游的线程是可以的, 也就是说每调用一次observeOn() , 下游的线程就会切换一次.

举个栗子——Retrofit+RxJava获取干货集中营的每个分类的数据

首先添加gradle配置

 //retrofit
 compile 'com.squareup.retrofit2:retrofit:2.1.0'
 //Gson converter
 compile 'com.squareup.retrofit2:converter-gson:2.1.0'
 //RxJava2 Adapter
 compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
 //okhttp
 compile 'com.squareup.okhttp3:okhttp:3.4.1'
 compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
public class ServiceFactory {

    private final Gson mGson;
    private OkHttpClient.Builder mBuilder;


    private ServiceFactory() {
        mGson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd hh:mm:ss")
                .create();

        mBuilder = new OkHttpClient.Builder();
        mBuilder.readTimeout(10, TimeUnit.SECONDS);
        mBuilder.connectTimeout(9, TimeUnit.SECONDS);
    }


    private static class SingletonHolder {
        private static final ServiceFactory INSTANCE = new ServiceFactory();
    }

    public static ServiceFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }


    public <S> S createService(Class<S> serviceClass) {
        String baseUrl = "";
        try {
            Field field1 = serviceClass.getField("BASE_URL");
            baseUrl = (String) field1.get(serviceClass);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.getMessage();
            e.printStackTrace();
        }
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(mBuilder.build())
                .addConverterFactory(GsonConverterFactory.create(mGson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        return retrofit.create(serviceClass);
    }
}
public interface GankService {

    String BASE_URL = "http://www.gank.io/api/";


    /***
     * 根据类别查询干货
     *
     * @param category
     * @param pageIndex
     * @return
     */
    @GET("data/{category}/20/{pageIndex}")
    Observable<HttpResult<List<GanHuoData>>> getGanHuo(@Path("category") String category
            , @Path("pageIndex") int pageIndex);


}
ServiceFactory.getInstance()
       .createService(GankService.class).getGanHuo("福利", 3)
       .observeOn(AndroidSchedulers.mainThread())//回到主线程去处理请求结果
       .subscribeOn(Schedulers.io())//在IO线程进行网络请求
       .subscribe(new Observer<HttpResult<List<GanHuoData>>>() {
   @Override
   public void onSubscribe(Disposable d) {

   }

   @Override
   public void onNext(HttpResult<List<GanHuoData>> value) {
       Log.d(TAG,"value'size:"+value.results.size());
   }

   @Override
   public void onError(Throwable e) {
       Log.e(TAG,e.getMessage());
  }

   @Override
   public void onComplete() {
       Log.d(TAG,"onComplete");
   }
});

这个例子写的很糙,用来获取20条“妹子”的数据,但我偷懒了只是简单展示了log而已,但问题不大。运行后的结果如下:

04-23 03:48:17.410 7881-7881/com.example.dawn4get.myapplication D/rx: value'size:20
04-23 03:48:17.410 7881-7881/com.example.dawn4get.myapplication D/rx: onComplete

看似很完美, 但我们忽略了一点, 如果在请求的过程中Activity已经退出了, 这个时候如果回到主线程去更新UI, 那么APP肯定就崩溃了, 怎么办呢, 上一节我们说到了Disposable , 说它是个开关, 调用它的dispose()方法时就会切断水管, 使得下游收不到事件, 既然收不到事件, 那么也就不会再去更新UI了. 因此我们可以在Activity中将这个Disposable 保存起来, 当Activity退出时, 切断它即可.

那如果有多个Disposable 该怎么办呢, RxJava中已经内置了一个容器CompositeDisposable, 每当我们得到一个Disposable时就调用CompositeDisposable.add()将它添加到容器中, 在退出的时候, 调用CompositeDisposable.clear() 即可切断所有的水管.

ok,本次的就到学习这里啦。本系列的下一篇文章,就是我们一起学习RxJava操作符的时候了,see u :)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值