RxJava系列 (九) 线程切换操作符

线程切换操作符, 是RxJava不可获取的操作符。

1.subscribeOn

用于给上游配置异步线程,即使给上游分配多次,只会在第一次切换,后面的不切换了。

2. observeOn

用于给下游配置异步线程,给下游分配多次,每次都会切换。以最后一次为准。

3. 线程类型

Schedulers.io(): 代表io流操作,网络操作,文件流等耗时操作。 里面其实就是一个线程池。

Schedulers.newThread:类似new Thread().start(). 用的比较少。没有RXJava加持

Schedulers.computation: 代表CPU大量计算所需要的线程。

AndroidSchedulers.mainThread():专门为android主线程量身定做。

        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Log.d("", "上游subscribe:" + Thread.currentThread().getId());

            }
        })
                //指定上游线程类型
                .subscribeOn(Schedulers.io()) //给上游配置异步线程,即使给上游分配多次,只会在第一次切换,后面的不切换了。
                .subscribeOn(AndroidSchedulers.mainThread())//被忽略
                .subscribeOn(AndroidSchedulers.mainThread())//被忽略
                //结果是:Schedulers.io(), 异步线程

                //指定下游线程类型
                .observeOn(AndroidSchedulers.mainThread())//给下游配置异步线程,给下游分配多次,每次都会切换。以最后一次为准。
                .observeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                //结果是:Schedulers.io(), 异步线程
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {

                    }
                });

在默认情况下,是主线程。所以结果是上游发送一次,下游就接到一次,然后上游才能发送下一次。这是一个同步的过程。

        //默认情况下。上游发送一次,下游就接到一次,然后上游才能发送下一次。这是一个同步的过程。
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Log.d("", "subscribe: 上游发送一次 1");
                emitter.onNext(1);

                Log.d("", "subscribe: 上游发送一次 2");
                emitter.onNext(2);

                Log.d("", "subscribe: 上游发送一次 3");
                emitter.onNext(3);
            }
        }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {

                Log.d("", "subscribe: 下游接收到" + integer);
            }
        });

在配置了异步以后。上游和下游各自执行自己的业务。上游可能连续输出三次,下游才接到第一次事件。

        //配置了异步以后。
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Log.d("", "subscribe: 上游发送一次 1");
                emitter.onNext(1);

                Log.d("", "subscribe: 上游发送一次 2");
                emitter.onNext(2);

                Log.d("", "subscribe: 上游发送一次 3");
                emitter.onNext(3);
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {

                        Log.d("", "subscribe: 下游接收到" + integer);
                    }
                });
    }

 

下面举一个实际使用的例子,用URL下载图片:

传统的模式是下面这样的:

    public void onClick7(View view) {
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("正在下载中。。。");
        progressDialog.show();

        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    URL url = new URL("http://cms-bucket.ws.126.net/2020/0308/f26c2480j00q6ujvz000yc000hi00b1c.jpg");

                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setConnectTimeout(5000);
                    int responseCode = urlConnection.getResponseCode();
                    if (responseCode == HTTP_OK) {
                        Bitmap bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());

                        Paint paint = new Paint();
                        paint.setColor(Color.RED);
                        paint.setTextSize(30);

                        Bitmap bitmapSuccess = drawTextToBitmap(bitmap, "hello 大家好", paint,60,60);
                        
                        Message message = handler.obtainMessage();
                        message.obj = bitmap;
                        handler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            Bitmap bitmap = (Bitmap) msg.obj;
            imageView.setImageBitmap(bitmap);
            if (progressDialog != null) {
                progressDialog.dismiss();
            }
            return false;
        }
    });

用RxJava如下:

第一转换操作符map,用于下载网络图片,相当于string转bitmap.

第二转换操作符map,用于给下载的图片,添加水印。

第三转换操作符map,用于缓存图片。

以上三个操作符,后面两个可以可以根据需求自由拆卸。每一个map都是一个链条或者卡片。当不需要添加水印的时候,把转水印的操作符去掉就可以了。

    public void onClick8(View view) {
        Observable.just("http://cms-bucket.ws.126.net/2020/0308/f26c2480j00q6ujvz000yc000hi00b1c.jpg")
                //根据url下载图片,相当于把string转成Bitmap
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String s) throws Exception {
                        URL url = new URL(s);

                        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                        urlConnection.setConnectTimeout(5000);
                        int responseCode = urlConnection.getResponseCode();
                        if (responseCode == HTTP_OK) {
                            Bitmap bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
                            return bitmap;
                        }
                        return null;
                    }
                })
                //给上游的Bitmap添加水印,再发给下游
                .map(new Function<Bitmap, Bitmap>() {
                    @Override
                    public Bitmap apply(Bitmap bitmap) throws Exception {
                        Paint paint = new Paint();
                        paint.setColor(Color.RED);
                        paint.setTextSize(30);
                        
                        Bitmap bitmapSuccess = drawTextToBitmap(bitmap, "hello 大家好", paint,60,60);
                        return bitmapSuccess;
                    }
                })
                //再给bitmap做个缓存
                .map(new Function<Bitmap, Bitmap>() {
                    @Override
                    public Bitmap apply(Bitmap bitmap) throws Exception {
                        //缓存一下
                        return bitmap;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        progressDialog = new ProgressDialog(MainActivity.this);
                        progressDialog.setMessage("正在下载中。。。");
                        progressDialog.show();
                    }

                    @Override
                    public void onNext(Bitmap bitmap) {
                        if (bitmap != null) {
                            imageView.setImageBitmap(bitmap);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        imageView.setImageDrawable(R.drawable.error);
                    }

                    @Override
                    public void onComplete() {
                        if (progressDialog != null) {
                            progressDialog.dismiss();
                        }
                    }
                });
    }

 

RxJava, 链式或者卡片式编程的好处,就是可以根据需求自由拆卸链条或者卡片。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值