RxJava详解(基于2.X版本的链式调用+线程切换)

本文详细介绍了RxJava中线程切换的原理及其在Android开发中的应用,包括默认线程行为、subscribeOn与observeOn方法的使用及源码解析。

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

1. RxJava详解(基于1.X版本)

https://blog.youkuaiyun.com/weixin_37730482/article/details/68059274

 

2.RxJava详解(基于2.X版本)

https://blog.youkuaiyun.com/weixin_37730482/article/details/69280013

 

 

本章节继续讲解RxJava的使用

 

 

Gradle依赖 RxJava&RxAndroid 版本须一致 即都是2.x版本

implementation 'io.reactivex.rxjava2:rxjava:2.0.1'

implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

 

 

 

一.RxJava基于事件流的链式调用

 

上述讲解RxJava的使用时,观察者被观察者的创建是分开的。其实两者可以合并在一起使用。这样代码看起来更加简洁。这就是RxJava基于事件流的链式调用

 

 

1.代码(单个订阅关系)

package com.example.rxjava20;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

public class MainActivity extends AppCompatActivity {

    private Disposable mDisposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        method1();
    }

    /**
     * RxJava基于事件流的链式调用
     * create操作符创建被观察者  最常用
     */

    public void method1() {
        Observable.create(new ObservableOnSubscribe<Object>() {
            @Override
            public void subscribe(ObservableEmitter<Object> e) throws Exception {
                if (e == null) {
                    return;
                }

                //没有切断与观察者的关联
                if (!e.isDisposed()) {
                    e.onNext("被观察者对象 发出第1波数据......");
                    e.onNext("被观察者对象 发出第2波数据......");
                    e.onNext("被观察者对象 发出第3波数据......");
                    e.onComplete();
                }

            }
        }).subscribe(new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable d) {
                if (null == d) {
                    return;
                }
                mDisposable = d;
                Log.d("TAG", "RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
            }

            @Override
            public void onNext(Object value) {
                Log.d("TAG", "RxJava链式调用1 观察者 onNext方法执行!!!结果:" + value.toString());
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "RxJava链式调用1 观察者 onError方法执行!!!");
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "RxJava链式调用1 观察者 onComplete方法执行!!!");
            }
        });
    }

    /**
     * onDestroy方法
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != mDisposable) {
            Log.d("TAG", "onDestroy方法 执行时是否断开----:" + mDisposable.isDisposed());
            if (!mDisposable.isDisposed()) {//没有断开
                mDisposable.dispose();//断开
                Log.d("TAG", "onDestroy方法 断开订阅");
            }
        }
    }

}

 

结果

D/TAG: RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:false

D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第1波数据......

D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第2波数据......

D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第3波数据......

D/TAG: RxJava链式调用1 观察者 onComplete方法执行!!!

 

关闭页面

D/TAG: onDestroy方法 执行时是否断开----:true

 

 

2.代码(多个订阅关系)

package com.example.rxjava20;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;

public class MainActivity extends AppCompatActivity {

    private CompositeDisposable mCompositeDisposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mCompositeDisposable = new CompositeDisposable();

        method1();
        method2();
        method3();
        method4();
    }

    /**
     * RxJava基于事件流的链式调用
     * create操作符创建被观察者  最常用
     */

    public void method1() {
        Observable.create(new ObservableOnSubscribe<Object>() {
            @Override
            public void subscribe(ObservableEmitter<Object> e) throws Exception {
                if (e == null) {
                    return;
                }

                //没有切断与观察者的关联
                if (!e.isDisposed()) {
                    e.onNext("被观察者对象 发出第1波数据......");
                    e.onNext("被观察者对象 发出第2波数据......");
                    e.onNext("被观察者对象 发出第3波数据......");
                    e.onComplete();
                }

            }
        }).subscribe(new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable d) {
                if (null == d) {
                    return;
                }
                mCompositeDisposable.add(d);
                Log.d("TAG", "RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
            }

            @Override
            public void onNext(Object value) {
                Log.d("TAG", "RxJava链式调用1 观察者 onNext方法执行!!!结果:" + value.toString());
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "RxJava链式调用1 观察者 onError方法执行!!!");
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "RxJava链式调用1 观察者 onComplete方法执行!!!");
            }
        });
    }

    /**
     * RxJava基于事件流的链式调用
     * Just操作符创建被观察者  发送的数据格式不统一 Int类型 String类型...
     */

    public void method2() {
        Observable.just("1", 23, "张三").subscribe(new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable d) {
                if (null == d) {
                    return;
                }
                mCompositeDisposable.add(d);
                Log.d("TAG", "RxJava链式调用2 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
            }

            @Override
            public void onNext(Object value) {
                Log.d("TAG", "RxJava链式调用2 观察者 onNext方法执行!!!结果:" + value.toString());
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "RxJava链式调用2 观察者 onError方法执行!!!");
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "RxJava链式调用2 观察者 onComplete方法执行!!!");
            }
        });
    }

    /**
     * RxJava基于事件流的链式调用
     * fromArray操作符创建被观察者  发送的数据为数组
     */

    public void method3() {
        String string[] = new String[]{"123", "fromArray操作符", "李四"};
        Observable.fromArray(string).subscribe(new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable d) {
                if (null == d) {
                    return;
                }
                mCompositeDisposable.add(d);
                Log.d("TAG", "RxJava链式调用3 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
            }

            @Override
            public void onNext(Object value) {
                Log.d("TAG", "RxJava链式调用3 观察者 onNext方法执行!!!结果:" + value.toString());
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "RxJava链式调用3 观察者 onError方法执行!!!");
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "RxJava链式调用3 观察者 onComplete方法执行!!!");
            }
        });
    }

    /**
     * RxJava基于事件流的链式调用
     * fromArray操作符创建被观察者 发送的数据为集合
     */

    public void method4() {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("张三");
        list.add("6598");
        list.add("我是集合");
        Observable.fromIterable(list).subscribe(new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable d) {
                if (null == d) {
                    return;
                }
                mCompositeDisposable.add(d);
                Log.d("TAG", "RxJava链式调用4 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
            }

            @Override
            public void onNext(Object value) {
                Log.d("TAG", "RxJava链式调用4 观察者 onNext方法执行!!!结果:" + value.toString());
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "RxJava链式调用4 观察者 onError方法执行!!!");
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "RxJava链式调用4 观察者 onComplete方法执行!!!");
            }
        });
    }

    /**
     * onDestroy方法
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != mCompositeDisposable) {
            Log.d("TAG", "onDestroy方法 执行时是否断开----:" + mCompositeDisposable.isDisposed());
            if (!mCompositeDisposable.isDisposed()) {//没有断开
                mCompositeDisposable.dispose();//断开
                Log.d("TAG", "onDestroy方法 断开订阅");
            }
        }
    }

}

 

 

结果

D/TAG: RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:false

D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第1波数据......

D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第2波数据......

D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第3波数据......

D/TAG: RxJava链式调用1 观察者 onComplete方法执行!!!




D/TAG: RxJava链式调用2 观察者 onSubscribe方法执行 是否断开连接----:false

D/TAG: RxJava链式调用2 观察者 onNext方法执行!!!结果:1

D/TAG: RxJava链式调用2 观察者 onNext方法执行!!!结果:23

D/TAG: RxJava链式调用2 观察者 onNext方法执行!!!结果:张三

D/TAG: RxJava链式调用2 观察者 onComplete方法执行!!!



D/TAG: RxJava链式调用3 观察者 onSubscribe方法执行 是否断开连接----:false

D/TAG: RxJava链式调用3 观察者 onNext方法执行!!!结果:123

D/TAG: RxJava链式调用3 观察者 onNext方法执行!!!结果:fromArray操作符

D/TAG: RxJava链式调用3 观察者 onNext方法执行!!!结果:李四

D/TAG: RxJava链式调用3 观察者 onComplete方法执行!!!



D/TAG: RxJava链式调用4 观察者 onSubscribe方法执行 是否断开连接----:false

D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:1

D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:2

D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:张三

D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:6598

D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:我是集合

D/TAG: RxJava链式调用4 观察者 onComplete方法执行!!!

 

 

关闭页面

D/TAG: onDestroy方法 执行时是否断开----:false

D/TAG: onDestroy方法 断开订阅

 

 

3.说明

<1> 正如上面demo中的样子,创建出 Observable(被观察者)Observer(观察者),再用 subscribe() 方法将它们订阅,一次 RxJava 的基本使用就完成了。非常简单。这就是RxJava基于事件流的链式调用

 

<2> 正如前一章节所述。单个订阅关系时 被观察者使用Create操作符时订阅关系会自动断开。无论是前一章节讲述的分开创建观察者和被观察者还是此章节讲述的链式调用。但是使用其他的操作符不会自动断开

 

<3> 但是多个订阅关系时,无论是使用什么操作符无论是前一章节讲述的分开创建观察者和被观察者还是此章节讲述的链式调用。订阅关系都不会自动断开不过这个情况比较少见

 

 

 

 

 

 

 

二.RxJava线程切换

在 RxJava 的默认规则中,事件的发出和消费都是在同一个线程的。也就是说,如果只用上面的方法,实现出来的只是一个同步的观察者模式。

观察者模式本身的目的就是『后台处理前台回调』的异步机制,因此异步对于 RxJava 是至关重要的。而要实现异步,则需要用到 RxJava 的另一个概念: Scheduler

 

1.默认情况

在 RxJava 的默认规则中,事件的发出和消费都是在同一个线程的

 

代码

package com.example.rxjava20;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

public class MainActivity extends AppCompatActivity {

    private Disposable disposable;
    private Observer observer = null;
    private Observable observable = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        createObserverMethod();//创建观察者对象
        createObservableMethod();//创建被观察者对象
        if (null != observer && null != observable) {
            observable.subscribe(observer);//完成订阅
        }

    }

    /**
     * 创建 观察者对象
     */

    public void createObserverMethod() {
        observer = new Observer() {
            @Override
            public void onSubscribe(Disposable d) {
                if (null == d) {
                    return;
                }
                disposable = d;
                Log.d("TAG", "观察者对象 onSubscribe方法 接收数据 是否断开连接----:" + disposable.isDisposed());
                Log.d("TAG", "观察者对象 onSubscribe方法 接收数据 线程----:" + Thread.currentThread().getName());
            }

            @Override
            public void onNext(Object value) {
                Log.d("TAG", "观察者对象 onNext方法 接收数据 结果:" + value.toString());
                Log.d("TAG", "观察者对象 onNext方法 接收数据 线程----:" + Thread.currentThread().getName());
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "观察者对象 onError方法 接收数据 线程----:" + Thread.currentThread().getName());
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "观察者对象 onComplete方法 接收数据 线程----:" + Thread.currentThread().getName());
            }
        };
    }

    /**
     * 创建 被观察者对象
     */

    public void createObservableMethod() {
        observable = Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {
                if (e == null) {
                    return;
                }

                //没有切断与观察者的关联
                if (!e.isDisposed()) {
                    e.onNext("被观察者对象发出第N波数据......");
                    e.onComplete();
                }

                Log.d("TAG", "被观察者对象 发送数据 线程----:" + Thread.currentThread().getName());
            }
        });
    }

    /**
     * onDestroy方法
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != disposable) {
            Log.d("TAG", "onDestroy方法 执行时是否断开----:" + disposable.isDisposed());
            if (!disposable.isDisposed()) {//没有断开
                disposable.dispose();//断开
                Log.d("TAG", "onDestroy方法 断开订阅");
            }
        }
    }

}

 

结果

D/TAG: 观察者对象 onSubscribe方法 接收数据 是否断开连接----:false

D/TAG: 观察者对象 onSubscribe方法 接收数据 线程----:main

D/TAG: 观察者对象 onNext方法 接收数据 结果:被观察者对象发出第N波数据......

D/TAG: 观察者对象 onNext方法 接收数据 线程----:main

D/TAG: 观察者对象 onComplete方法 接收数据 线程----:main



D/TAG: 被观察者对象 发送数据 线程----:main

 

关闭页面

D/TAG: onDestroy方法 执行时是否断开----:true

 

验证的结论就是:

在 RxJava 的默认规则中,事件的发出和消费都是在同一个线程的。这显然不是我们要的。

 

因为我们希望:

<1> 被观察者Observable) 在 子线程生产事件(如实现耗时操作/IO操作/CPU大量计算等等)。
 

<2> 观察者Observer)在 主线程接收事件(即实现UI操作)。

 

所以:

为了解决上述冲突,即实现 真正的异步操作,我们需要对RxJava进行 线程控制(也称为调度 / 切换)。

 

 

 

2.线程切换
 

<1> 简介

采用 RxJava内置的线程调度器( Scheduler ),即通过 功能性操作符 subscribeOn()  observeOn() 实现。

 

 

<2> 作用

线程控制,即指定 被观察者 (Observable) / 观察者(Observer) 的工作线程类型。

 

 

<3> 线程类型

在 RxJava中,内置了多种用于调度的线程类型

类型含义应用场景
Schedulers.immediate()不指定线程默认
Schedulers.newThread()开启新线程耗时等操作
Schedulers.io()io操作线程网络请求、读写文件等io密集型操作
Schedulers.computation()CPU计算操作线程大量计算操作 比如图片压缩取样、大量数据的Json解析等CPU密集型计算
AndroidSchedulers.mainThread()Android主线程操作UI

 

 

 

 

 

 

 

 

<4> 修改上述代码 

即 修改 观察者和被观察者的订阅关系代码

if (null != observer && null != observable) {
    observable.subscribeOn(Schedulers.newThread()) //指定被观察者 生产事件的线程
            .observeOn(AndroidSchedulers.mainThread())  //指定观察者 接收 & 响应事件的线程
            .subscribe(observer); //最后再通过订阅(subscribe)连接观察者和被观察者
}

 

 

<5> 结果

D/TAG: 观察者对象 onSubscribe方法 接收数据 是否断开连接----:false

D/TAG: 观察者对象 onSubscribe方法 接收数据 线程----:main


D/TAG: 观察者对象 onNext方法 接收数据 结果:被观察者对象发出第N波数据......

D/TAG: 观察者对象 onNext方法 接收数据 线程----:main

D/TAG: 观察者对象 onComplete方法 接收数据 线程----:main





D/TAG: 被观察者对象 发送数据 线程----:RxNewThreadScheduler-1

 

 

<6> 结论

观察者在UI线程接收数据被观察者在子线程发送数据

 

 

<7> 再举例 使用Schedulers.io() 一般进行网络请求

if (null != observer && null != observable) {
    observable.subscribeOn(Schedulers.io()) //指定被观察者 生产事件的线程
            .observeOn(AndroidSchedulers.mainThread())  //指定观察者 接收 & 响应事件的线程
            .subscribe(observer); //最后再通过订阅(subscribe)连接观察者和被观察者
}

 

结果

D/TAG: 观察者对象 onSubscribe方法 接收数据 是否断开连接----:false

D/TAG: 观察者对象 onSubscribe方法 接收数据 线程----:main

D/TAG: 观察者对象 onNext方法 接收数据 结果:被观察者对象发出第N波数据......

D/TAG: 观察者对象 onNext方法 接收数据 线程----:main

D/TAG: 观察者对象 onComplete方法 接收数据 线程----:main





D/TAG: 被观察者对象 发送数据 线程----:RxCachedThreadScheduler-1

 

 

<8> 注意

(1) Observable.subscribeOn(XXX) 多次执行 即多次指定被观察者所在的线程。以第一次为准。

 

代码

if (null != mSubscriber && null != observable) {
    observable.subscribeOn(Schedulers.io()) //第一次 指定被观察者 生产事件的线程 IO
            .subscribeOn(Schedulers.newThread())//第二次 指定被观察者 生产事件的线程 新线程
            .observeOn(AndroidSchedulers.mainThread())  //指定观察者 接收 & 响应事件的线程
            .subscribe(mSubscriber); //最后再通过订阅(subscribe)连接观察者和被观察者
}

 

结果  IO线程

D/TAG: 被观察者 发送数据 线程----:RxIoScheduler-2


D/TAG: 观察者 onNext方法 线程----:main

D/TAG: 观察者 onCompleted方法 线程----:main

 

(2) Observable.observeOn(XXX) 执行多次 即多次指定观察者所在的线程 每调用一次,观察者的线程就会切换一次。以最后一次为准。

 

 

 

<9> RxJava&RxAndroid线程问题具体使用

Android 网络系列:https://blog.youkuaiyun.com/weixin_37730482/category_6875815.html

 

 

 

 

 

三.RxJava线程切换原理

 

上述讲述了RxJava观察者和被观察者默认所处的线程以及手动指定观察者和被观察者所在的线程。那么线程切换的原理是什么呢?

 

1.先来看两段代码

 

代码1

package com.example.rxjava20;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testMethod();
    }

    private void testMethod() {
        Log.d("TAG", "Thread run() 所在线程为 :" + Thread.currentThread().getName());
        Observable
                .create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                        Log.d("TAG", "被观察者 subscribe()方法 所在线程为 :" + Thread.currentThread().getName());
                        emitter.onNext("111111");
                        emitter.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())//指定被观察者所在的线程 IO线程
                .observeOn(AndroidSchedulers.mainThread())//指定观察者所在的线程 UI线程
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d("TAG", "观察者 onSubscribe()方法 所在线程为 :" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("TAG", "观察者 onNext()方法 所在线程为 :" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("TAG", "观察者 onError()方法 所在线程为 :" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onComplete() {
                        Log.d("TAG", "观察者 onComplete()方法 所在线程为 :" + Thread.currentThread().getName());
                    }
                });
    }

}

 

结果1

D/TAG: Thread run() 所在线程为 :main

D/TAG: 观察者 onSubscribe()方法 所在线程为 :main

D/TAG: 被观察者 subscribe()方法 所在线程为 :RxCachedThreadScheduler-1

D/TAG: 观察者 onNext()方法 所在线程为 :main

D/TAG: 观察者 onComplete()方法 所在线程为 :main

 

结论1

默认情况下 即观察者和被观察者订阅的方法运行在UI线程

观察者四个方法onSubscribe()方法+onNext()方法+onComplete()方法(onError方法)都运行在observeOn(AndroidSchedulers.mainThread());指定观察者所在的线程中。

被观察者subscribe方法即发送事件的方法运行在subscribeOn(Schedulers.io())//指定被观察者所在的线程中。

 

 

代码2

new Thread(new Runnable() {
     @Override
     public void run() {
          testMethod();
     }
}).start();

即 修改上述testMethod()方法所在的线程。

 

 

结果2

D/TAG: Thread run() 所在线程为 :Thread-6


D/TAG: 观察者 onSubscribe()方法 所在线程为 :Thread-6


D/TAG: 被观察者 subscribe()方法 所在线程为 :RxCachedThreadScheduler-1


D/TAG: 观察者 onNext()方法 所在线程为 :main



D/TAG: 观察者 onComplete()方法 所在线程为 :main

 

结论2

这种情况 即观察者和被观察者订阅的方法运行在新线程

观察者的三个方法onNext()方法+onComplete()方法(onError方法)都运行在.observeOn(AndroidSchedulers.mainThread());指定观察者所在的线程中。

观察者onSubscribe()方法运行在当前线程中。

被观察者的subscribe方法即发送事件的方法运行在.subscribeOn(Schedulers.io())//指定被观察者所在的线程中。

 

综上所述 

observeOn()方法:指定观察者所在的线程。onSubscribe()方法除外。onSubscribe()方法所在的线程与当前线程一致。

subscribeOn()方法:指定被观察者所在的线程。

 

 

2.源码分析

 

首先 subscribeOn方法 指定被观察者所在的线程

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}

第一行代码可以忽略,我们直接看第二行代码。

 

第二行代码

RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
    Function<? super Observable, ? extends Observable> f = onObservableAssembly;
    if (f != null) {
        return apply(f, source);
    }
    return source;
}

这个方法就是操作了Observable<T> source这个参数。显然最重要的是new ObservableSubscribeOn<T>(this, scheduler)。

 

ObservableSubscribeOn类源码

public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;

    public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
        super(source);
        this.scheduler = scheduler;
    }

    @Override
    public void subscribeActual(final Observer<? super T> s) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);

        s.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                source.subscribe(parent);
            }
        }));
    }


...

}

 

可见,在subscribeActual方法中。调用了

source.subscribe(parent);

也就是说,ObservableSubscribeOn类中的subscribeActual方法中调用了被观察者subscribe方法。也就是说被观察者subscribe()方法所在的线程是在这个方法中确定的。

parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
     @Override
     public void run() {
          source.subscribe(parent);
     }
}));

调用了Scheduler类scheduler对象scheduleDirect方法。也就是说scheduler对象线程决定了被观察者的subscribe方法所在的线程。scheduler对象线程也就是subscribeOn()方法传过来的RxJava线程调度类的对象。这里就是subscribeOn(Schedulers.io())。

 

 

再来看observeOn()方法 指定观察者所在的线程

public final Observable<T> observeOn(Scheduler scheduler) {
   return observeOn(scheduler, false, bufferSize());
}

observeOn方法中第一个参数就是传入的线程,第三个参数是缓存大小。

 

先看缓存大小

public static int bufferSize() {
   return Flowable.bufferSize();
}

 

public static int bufferSize() {
   return BUFFER_SIZE;
}

 

public abstract class Flowable<T> implements Publisher<T> {
    /** The default buffer size. */
    static final int BUFFER_SIZE;
    static {
        BUFFER_SIZE = Math.max(16, Integer.getInteger("rx2.buffer-size", 128));
    }

...
}

 

缓存就是16和128的最大值。

 

再看observeOn方法

@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    ObjectHelper.verifyPositive(bufferSize, "bufferSize");
    return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}

同理,忽略前两行代码直接看第三行。也有一个new对象。ObservableObserveOn对象。

 

ObservableObserveOn类源码

public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;
    final boolean delayError;
    final int bufferSize;
    public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
        super(source);
        this.scheduler = scheduler;
        this.delayError = delayError;
        this.bufferSize = bufferSize;
    }


 @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }


 static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

        private static final long serialVersionUID = 6576896619930983584L;
        final Observer<? super T> actual;
        final Scheduler.Worker worker;
        final boolean delayError;
        final int bufferSize;

    ...
  } 









...
}

该类中。有观察者的四个方法。

onSubscribe方法

@Override
public void onSubscribe(Disposable s) {
    if (DisposableHelper.validate(this.s, s)) {
        this.s = s;
        if (s instanceof QueueDisposable) {
            @SuppressWarnings("unchecked")
            QueueDisposable<T> qd = (QueueDisposable<T>) s;

            int m = qd.requestFusion(QueueDisposable.ANY | QueueDisposable.BOUNDARY);

            if (m == QueueDisposable.SYNC) {
                sourceMode = m;
                queue = qd;
                done = true;
                actual.onSubscribe(this);
                schedule();
                return;
            }
            if (m == QueueDisposable.ASYNC) {
                sourceMode = m;
                queue = qd;
                actual.onSubscribe(this);
                return;
            }
        }

        queue = new SpscLinkedArrayQueue<T>(bufferSize);

        actual.onSubscribe(this);
    }
}

 

onNext方法

@Override
public void onNext(T t) {
    if (done) {
        return;
    }

    if (sourceMode != QueueDisposable.ASYNC) {
        queue.offer(t);
    }
    schedule();
}

onError方法 

@Override
public void onError(Throwable t) {
    if (done) {
        RxJavaPlugins.onError(t);
        return;
    }
    error = t;
    done = true;
    schedule();
}

onComplete方法 

@Override
public void onComplete() {
    if (done) {
       return;
    }
    done = true;
    schedule();
}

 

可以看出,onNext+onError+onComplete方法中,都有schedule方法。但是onSubscribe方法中没有schedule方法。schedule方法就是用来切换线程的。

 

schedule方法源码

void schedule() {
    if (getAndIncrement() == 0) {
        worker.schedule(this);
    }
}

可以看出worker切换线程,而worker就是上面的构造方法传过来的

final Scheduler.Worker worker;

 

构造方法

ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
   this.actual = actual;
   this.worker = worker;
   this.delayError = delayError;
   this.bufferSize = bufferSize;
}

 

也就是new这个类的时候传过来的。

return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));

 

new这个类的地方就是observeOn方法,即设置观察者所在的线程的方法

observeOn(AndroidSchedulers.mainThread())//指定观察者所在的线程 UI线程

 

这样就能解析,观察者四个方法所在的线程切换的原理了。

 

 

 

 

 

 

四.RxJava线程切换在Android中的运用

 

Android项目中,经常会遇到线程切换的问题,比如网络请求(IO线程)后需要切换线程在UI线程中更新View。比如在一个数据库操作(IO线程)后需要切换线程在UI线程中更新View。等等。这个时候如果在Activity中可以使用Activity的runOnUiThread()。

Activity的runOnUiThread()方法源码

public final void runOnUiThread(Runnable action) {
    if (Thread.currentThread() != mUiThread) {
        mHandler.post(action);
    } else {
        action.run();
    }
}

解释:

当前线程不是UI线程,使用Handler切换到主线程。

当前线程是UI线程,则直接run传入的Runnable对象。

 

那么如果需要切换线程的类不是在Activity中,或者获取Activity不是很方便的时候,怎么切换线程呢?

 

你可能会这样操作

Handler handler=new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
    @Override
    public void run() {
                
    }
});

 

但是这样new一个Handler,最好有地方销毁他。如果没有一个地方销毁他,可能会造成内存泄漏。那么有没有其他的办法呢?

 

如果项目中引入了RxJava和RxAndroid的话,可以使用他们来解决

 

代码

package com.wjn.rxdemo.rxjava;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import com.wjn.rxdemo.R;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;

public class RxJavaActivity extends AppCompatActivity {

    private Disposable mDisposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxjava);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("TAG", "当前线程:" + Thread.currentThread().getName());
                runAndroidUI(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("TAG", "被观察者执行线程:" + Thread.currentThread().getName());
                    }
                });
            }
        }).start();
    }

    /**
     * RxJava 切换Android主线程
     */

    private void runAndroidUI(Runnable runnable) {
        if (null == runnable) return;
        Observable
                .empty()//empty操作符 创建一个不发射任何数据但是正常终止的Observable(被观察者)
                .observeOn(AndroidSchedulers.mainThread())//指定观察者所在线程
                .doOnSubscribe(disposable -> mDisposable = disposable)//观察者订阅时调用
                .doOnComplete(() -> {//empty操作符 发送的被观察者 只会在观察者的onComplete方法接收
                    runnable.run();
                    if (null != mDisposable) {
                        boolean b = mDisposable.isDisposed();
                        Log.d("TAG", "是否取消订阅:" + b);
                        if (!b) {
                            mDisposable.dispose();
                            Log.d("TAG", "线程切换后取消订阅关系");
                        }
                    }
                })
                .subscribe();//订阅
    }

    /**
     * onDestroy方法 取消订阅
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        boolean b = mDisposable.isDisposed();
        Log.d("TAG", "关闭页面时是否取消订阅:" + b);
    }
}

 

结果

D/TAG: 当前线程:Thread-3


D/TAG: 被观察者执行线程:main


D/TAG: 是否取消订阅:false


D/TAG: 线程切换后取消订阅关系


D/TAG: 关闭页面时是否取消订阅:true

 

 

如果切换线程时,需要延时XX后执行呢?

 

代码

package com.wjn.rxdemo.rxjava;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import com.wjn.rxdemo.R;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;

public class RxJavaActivity extends AppCompatActivity {

    private Disposable mDisposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxjava);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("TAG", "当前线程:" + Thread.currentThread().getName());
                runAndroidUI(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("TAG", "被观察者执行线程:" + Thread.currentThread().getName());
                    }
                }, 5);
            }
        }).start();
    }

    /**
     * RxJava 切换Android主线程
     */

    private void runAndroidUI(Runnable runnable, int time) {
        if (null == runnable) return;
        Observable
                .timer(time, TimeUnit.SECONDS)//timer操作符 延时time(第二个参数是延时单位)发射Observable(被观察者)
                .observeOn(AndroidSchedulers.mainThread())//指定观察者所在线程
                .doOnSubscribe(disposable -> mDisposable = disposable)//观察者订阅时调用
                .doOnComplete(() -> {//在观察者的onComplete方法接收
                    runnable.run();
                    if (null != mDisposable) {
                        boolean b = mDisposable.isDisposed();
                        Log.d("TAG", "是否取消订阅:" + b);
                        if (!b) {
                            mDisposable.dispose();
                            Log.d("TAG", "线程切换后取消订阅关系");
                        }
                    }
                })
                .subscribe();//订阅
    }

    /**
     * onDestroy方法 取消订阅
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        boolean b = mDisposable.isDisposed();
        Log.d("TAG", "关闭页面时是否取消订阅:" + b);
    }
}

 

 

结果

11:43:27.537 5972-6020/com.wjn.rxdemo D/TAG: 当前线程:Thread-3


//5秒后 27+5=32

11:43:32.582 5972-5972/com.wjn.rxdemo D/TAG: 被观察者执行线程:main

11:43:32.582 5972-5972/com.wjn.rxdemo D/TAG: 是否取消订阅:false

11:43:32.582 5972-5972/com.wjn.rxdemo D/TAG: 线程切换后取消订阅关系




D/TAG: 关闭页面时是否取消订阅:true

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值