八、RxJava线程切换subscribeOn,observeOn

本文探讨了如何在Android应用中使用RxJava进行线程管理,包括默认线程配置、异步与主线程切换规律,以及结合实际场景如图片加载和添加文字的操作。同时,提到了必要的依赖和问题反思。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.项目地址

在MainActivity8

2.讲解

获取线程名字方法:

//获取当前的线程name(是主线程还是异步线程)
    private String getCurrentThread() {
        return Thread.currentThread().getName();
    }

1.默认线程

上下游默认都是主线程

2.为上游设置异步线程,下游设置主线程

//上游配置异步线程,下游配置主线程,RxJava内部是一个线程池
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
                Log.d(TAG, "subscribe: " + getCurrentThread());
                emitter.onNext(1);
            }
        })
                .subscribeOn(Schedulers.io())//给上游配置异步线程
                .observeOn(AndroidSchedulers.mainThread())//给下游配置主线程
                .subscribe(
                        new Consumer<Integer>() {
                            @Override
                            public void accept(Integer integer) throws Throwable {
                                Log.d(TAG, "accept: " + getCurrentThread());
                            }
                        }
                );
subscribeOn(Schedulers.io())

为上游线程设置异步线程

observeOn(AndroidSchedulers.mainThread())

为下游设置主线程

3.上游切换只有第一次生效,下游切换多次,算最后一次的线程设置

下列中,上游执行了多次subscribeOn,最后还是算第一个设置的,第一个设置为subscribeOn(Schedulers.io()),既上游还是异步线程。而下游也多次设置了observeOn
它算最后一次设置的线程,最后设置为observeOn(Schedulers.io()),所以为异步线程

 //上游配置多次线程,只会第一个切换,其他的不切换
        //下游配置多次线程,算最后一次的线程配置
        //上游配置异步线程,下游配置主线程,RxJava内部是一个线程池
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
                Log.d(TAG, "subscribe: " + getCurrentThread());
                emitter.onNext(1);
            }
        })
                .subscribeOn(Schedulers.io())//给上游配置异步线程
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.mainThread())

                .observeOn(AndroidSchedulers.mainThread())//给下游配置主线程
                .observeOn(Schedulers.io())//给上游配置异步线程
                .observeOn(AndroidSchedulers.mainThread())//给下游配置主线程
                .observeOn(AndroidSchedulers.mainThread())//给下游配置主线程
                .observeOn(Schedulers.io())//给上游配置异步线程
                .subscribe(
                        new Consumer<Integer>() {
                            @Override
                            public void accept(Integer integer) throws Throwable {
                                Log.d(TAG, "accept: " + getCurrentThread());
                            }
                        }
                );

4.默认线程发射与接收规律。设置后的发射与接收规律

//不配置的话,默认是发送一次,接收一次
        //上游配置异步线程,下游配置主线程,RxJava内部是一个线程池
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
                Log.d(TAG, "subscribe: " + "发送第1次");
                emitter.onNext(1);
                Log.d(TAG, "subscribe: " + "发送第2次");
                emitter.onNext(2);
                Log.d(TAG, "subscribe: " + "发送第3次");
                emitter.onNext(3);

            }
        })
                .subscribe(
                        new Consumer<Integer>() {
                            @Override
                            public void accept(Integer integer) throws Throwable {
                                Log.d(TAG, "下游accept: " + integer);
                            }
                        }
                );
        Log.d(TAG, "r3: --------------下游配置下");
        //下面是上游配置异步线程,下游配置主线程。异步线程会全部发送完,在接收
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
                Log.d(TAG, "subscribe: " + "发送第1次");
                emitter.onNext(1);
                Log.d(TAG, "subscribe: " + "发送第2次");
                emitter.onNext(2);
                Log.d(TAG, "subscribe: " + "发送第3次");
                emitter.onNext(3);
            }
        })
                .subscribeOn(Schedulers.io())//给上游配置异步线程
                .observeOn(AndroidSchedulers.mainThread())//给下游配置主线程
                .subscribe(
                        new Consumer<Integer>() {
                            @Override
                            public void accept(Integer integer) throws Throwable {
                                Log.d(TAG, "下游accept: " + integer);
                            }
                        }
                );

运行结果:
在这里插入图片描述
没配置前是发送一次接收一次。配置后为先发射完,后再接收

5.加载图片

1.普通方法来加载加载图片
//不使用RxJava去加载一张图片
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("下载中……");
        progressDialog.show();

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

                try {
                    Thread.sleep(2000);
                    URL url = new URL(PATH);
                    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                    httpURLConnection.setConnectTimeout(5000);
                    int responseCode = httpURLConnection.getResponseCode();
                    if (responseCode == HttpURLConnection.HTTP_OK) {
                        Bitmap bitmap = BitmapFactory.decodeStream(httpURLConnection.getInputStream());
                        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(@androidx.annotation.NonNull Message msg) {
            Bitmap bitmap = (Bitmap) msg.obj;
            imageView.setImageBitmap(bitmap);
            //隐藏加载框
            if (progressDialog != null) {
                progressDialog.dismiss();
            }
            return false;
        }
    });
2.用RxJava来加载图片

图片的连接:

String PATH = "https://img2.baidu.com/it/u=586607866,2734281005&fm=26&fmt=auto";
//Rxjava来加载图片,字符串Path转bitmap,然后加载
        Observable.just(PATH)
                //String path 变换 Bitmap
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String s) throws Throwable {
                        try {
                            Thread.sleep(2000);
                            URL url = new URL(PATH);
                            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                            httpURLConnection.setConnectTimeout(5000);
                            int responseCode = httpURLConnection.getResponseCode();
                            if (responseCode == HttpURLConnection.HTTP_OK) {
                                Bitmap bitmap = BitmapFactory.decodeStream(httpURLConnection.getInputStream());
                                return bitmap;
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
                })
                .subscribeOn(Schedulers.io())//给上游分配异步线程
                .observeOn(AndroidSchedulers.mainThread())//给下游分配 主线程
                .subscribe(new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        progressDialog=new ProgressDialog(MainActivity8.this);
                        progressDialog.setMessage("RxJava下载图片中……");
                        progressDialog.show();
                    }

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

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

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

运行结果:

在这里插入图片描述

6.进行中间操作,为图片添加一段文字

//Rxjava来加载图片,字符串Path转bitmap,然后加载
        Observable.just(PATH)
                //String path 变换 Bitmap
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String s) throws Throwable {
                        try {
                            Thread.sleep(2000);
                            URL url = new URL(PATH);
                            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                            httpURLConnection.setConnectTimeout(5000);
                            int responseCode = httpURLConnection.getResponseCode();
                            if (responseCode == HttpURLConnection.HTTP_OK) {
                                Bitmap bitmap = BitmapFactory.decodeStream(httpURLConnection.getInputStream());
                                return bitmap;
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
                })
                .subscribeOn(Schedulers.io())//给上游分配异步线程
                .observeOn(AndroidSchedulers.mainThread())//给下游分配 主线程
                .map(new Function<Bitmap, Bitmap>() {
                    @Override
                    public Bitmap apply(Bitmap bitmap) throws Throwable {
                        //给图片加水印
                        Paint paint=new Paint();
                        paint.setColor(Color.RED);
                        paint.setTextSize(30);
                        Bitmap bitmapSuccess=drawTextToBitmap(bitmap,"西门吹雪",paint,60,60);
                        return bitmapSuccess;
                    }
                })
                .subscribe(new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        progressDialog=new ProgressDialog(MainActivity8.this);
                        progressDialog.setMessage("RxJava下载图片中……");
                        progressDialog.show();
                    }

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

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        if (progressDialog!=null) {
                            progressDialog.dismiss();
                        }
                    }
                });
//图片上绘制文字
    private Bitmap drawTextToBitmap(Bitmap bitmap, String text, Paint paint,int paddingLeft,int paddingTop){
        Bitmap.Config bitmapConfig=bitmap.getConfig();
        paint.setDither(true);
        paint.setFilterBitmap(true);//过滤一些
        if (bitmapConfig==null) {
            bitmapConfig=Bitmap.Config.ARGB_8888;
        }
        bitmap=bitmap.copy(bitmapConfig,true);
        Canvas canvas=new Canvas(bitmap);

        canvas.drawText(text,paddingLeft,paddingTop,paint);
        return bitmap;
    }

运行结果:
在这里插入图片描述

3.问题与反思

要两个依赖

implementation "io.reactivex.rxjava3:rxjava:3.1.2"
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值