Rxjava学习笔记(二)

Rxjava学习(二)

关于Rxjava的线程控制

正常情况下,上游和下游是工作在同一个线程中的,也就是说:上游在哪个线程中发送事件,下游就在哪个线程中接收事件


在Android中,一个Activity的所有默认动作都是在主线程中进行的:


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, Thread.currentThread().getName());
    }

//结果
03-14 08:03:04.779 5051-5051/com.example.uds.recyclerviewtest D/MAP: main

在RxJava中:

当我们在主线程中创建一个上游 Observable 来发送事件,则这个上游就默认在主线程中发送事件


当我们在主线程中去创建一个下游 Observer 来接收事件,则这个下游默认就在主线程中接收事件


         Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                Log.d(TAG, Thread.currentThread().getName());
            }
        });

        Consumer<Integer> consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d(TAG,Thread.currentThread().getName());
            }
        };

        observable.subscribe(consumer);


//结果
03-14 08:03:04.779 5051-5051/com.example.uds.recyclerviewtest D/MAP: main
03-14 08:09:21.643 10661-10661/com.example.uds.recyclerviewtest D/MAP: main


我们的正常需求是在子线程中作耗时操作,然后回到主线程中来更新UI

所以就要求上游是在子线程中进行发送事件,下游是在主线程中接收事件的



        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                Log.d(TAG,Thread.currentThread().getName());
                e.onNext(1);

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

//结果
03-14 08:17:29.620 17840-17913/com.example.uds.recyclerviewtest D/MAP: RxNewThreadScheduler-1
03-14 08:17:29.798 17840-17840/com.example.uds.recyclerviewtest D/MAP: 1 onNext
03-14 08:17:29.798 17840-17840/com.example.uds.recyclerviewtest D/MAP: main


subscribeOn(Schedules.newThread()) 方法表示上游事件发生的线程位置,新建了一个线程

observeOn(AndroidSchedulers.mainThread()) 方法表示观察者即下游事件发生的线程位置,在主线程中

当我们把上述内容放到线程中,observeOn(AndroidSchedulers.mainThread()) 依然是表示在主线程中



         new Thread(new Runnable() {
           @Override
           public void run() {
               Observable.create(new ObservableOnSubscribe<Integer>() {
                   @Override
                   public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                       Log.d(TAG,Thread.currentThread().getName());
                       e.onNext(1);

                   }
               }).subscribeOn(Schedulers.newThread())
                       .observeOn(AndroidSchedulers.mainThread())
                       .subscribe(new Consumer<Integer>() {
                           @Override
                           public void accept(Integer integer) throws Exception {
                               Log.d(TAG,integer + " onNext");
                               try {
                                   Thread.sleep(2000);
                               } catch (InterruptedException e) {
                                   e.printStackTrace();
                               }
                               textView.setText("2");//布局文件定义了一个TextView
                               Log.d(TAG,Thread.currentThread().getName());
                           }
                       });



           }
       }).start();

指定线程的特点

subscribeOn() :指定上游发送事件的线程

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

observeOn() :指定下游接收事件的线程

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


        Observable.create(new ObservableOnSubscribe<Integer>() {
                   @Override
                   public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                       Log.d(TAG,Thread.currentThread().getName());
                       e.onNext(1);
                   }
               }).subscribeOn(Schedulers.newThread())
                       .observeOn(AndroidSchedulers.mainThread())
                       .doOnNext(new Consumer<Integer>() {
                           @Override
                           public void accept(Integer integer) throws Exception {
                               Log.d(TAG,"After observeOn Main");
                           }
                       })
                       .observeOn(Schedulers.io())
                       .doOnNext(new Consumer<Integer>() {
                           @Override
                           public void accept(Integer integer) throws Exception {
                               Log.d(TAG,"After observeOn io");
                           }
                       })
                       .subscribe(new Consumer<Integer>() {
                           @Override
                           public void accept(Integer integer) throws Exception {
                               Log.d(TAG,integer + " onNext");

                               Log.d(TAG,Thread.currentThread().getName());
                           }
                       });

//结果

03-14 13:52:27.900 7134-7200/com.example.uds.recyclerviewtest D/MAP: RxNewThreadScheduler-1
03-14 13:52:28.064 7134-7134/com.example.uds.recyclerviewtest D/MAP: After observeOn Main
03-14 13:52:28.077 7134-7206/com.example.uds.recyclerviewtest D/MAP: After observeOn io
03-14 13:52:28.077 7134-7206/com.example.uds.recyclerviewtest D/MAP: 1 onNext
03-14 13:52:28.077 7134-7206/com.example.uds.recyclerviewtest D/MAP: RxCachedThreadScheduler-1

RxJavaz中内置的线程

  • Schedulers.io() 代表io操作的线程,通常用于网络,读写文件等io密集型的操作
  • Schedulers.computation() 代表CPU计算密集型的操作,例如需要大量计算的操作
  • Schedulers.newThread() 代表一个常规的新线程
  • AndroidSchedulers.mainThread() 代表Android的主线程


这些类型的线程在Rxjava中使用了线程池来进行了维护,所以效率较高我们可以直接使用

网络请求

如下的例子是在上游进行网络请求,然后在下游更新UI,会存在如下问题,当我们网络请求完毕去更新UI的时候,Activity退出了就会出现APP崩溃的问题


public interface API{
    @POST
    @FormUrlEncoded
    Observable<Response> login(@Field("username") String username ,@Field("password") String password)
}


Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("xxxx")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory)
            .build();

API api = retrofit.create(API.class);

api.login("admin","admin")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<Response>(){
                @Override
                public void onSubscribe(Disposable d) {}

                @Override
                public void onNext(LoginResponse value) {}

                @Override
                public void onError(Throwable e) {
                    Toast.makeText(mContext, "登录失败", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onComplete() {
                    Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show();
                }
        });

这里我们就需要将 Disposable 对象进行保存 ,在退出activity的时候将管道切断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值