【Rxjava详解】(五)执行原理

我们从源码的角度去分析一下RxJava的各个角色的api原理,以及如何进行线程切换和导致内存泄漏的原因。

笔者为初学者,很多知识来源于几年前的书籍和别人博客,部分涉及到的方法或者类在rxjava的新版本被弃用。

Observable源码分析

先看一下Observable.create()方法:

Observable.create() 方法是 RxJava 中创建 Observable 对象的静态方法,它接收一个 ObservableOnSubscribe 参数,用于定义被观察者发出数据的行为,

public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
    Objects.requireNonNull(source, "source is null");
    return new ObservableCreate<>(source);
}

Observable.create() 方法首先会检查传入的 ObservableOnSubscribe 对象是否为 null,如果为 null,则抛出 NullPointerException 异常。然后,它会创建一个 ObservableCreate 对象,并将传入的 ObservableOnSubscribe 对象作为参数传给它。

ObservableCreate 是 Observable 的一个内部类,它实现了 Observable 类的核心逻辑,用于管理订阅、发射数据等操作。下面是 ObservableCreate 类的部分源码:

static final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<>(observer);
        observer.onSubscribe(parent);

        try {
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }
}

static final class CreateEmitter<T> extends AtomicBoolean implements ObservableEmitter<T>, Disposable {
    ....

    @Override
    public void onNext(T value) {
        // 发射数据项给观察者
        if (!isDisposed()) {
            if (value == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
            observer.onNext(value);
        }
    }

    // 省略
}

在 ObservableCreate 类中,首先在 subscribeActual() 方法中,创建了一个 CreateEmitter 对象,并将传入的 Observer 对象作为参数传给它。然后,调用传入的 ObservableOnSubscribe 对象的 subscribe() 方法。在 subscribe() 方法中,定义了被观察者发出数据的行为。

CreateEmitter 类是 ObservableCreate 的内部类(看得我眼花缭乱),它实现了 ObservableEmitter 接口,用于发射数据和处理订阅状态。在 onNext() 方法中,会将接收到的数据项发射给观察者。

综上,Observable.create() 方法的核心逻辑是创建一个 ObservableCreate 对象,并将传入的 ObservableOnSubscribe 对象作为参数传给它,然后通过 ObservableCreate 对象来管理订阅和发射数据的操作。

Subscriber浅析

以下是附带注释的源码,并不完全

public abstract class Subscriber<T> implements Observer<T>, Subscription {
    // 初始请求数量未设置的标志
    private static final long NOT_SET = Long.MIN_VALUE;

    // 订阅列表
    private final SubscriptionList subscriptions = new SubscriptionList();

    // 支持背压和持有订阅列表的Subscriber对象
    private Subscriber<?> subscriber;

    // 请求通道,建立Observable和Subscriber之间的请求通道
    private Producer producer;

    // 请求的数量,默认为NOT_SET表示未设置
    private long requested = NOT_SET;

    // 构造方法
    public Subscriber() {
    }

    // 使用另一个Subscriber对象作为背压的构造方法
    public Subscriber(Subscriber<?> subscriber) {
        this.subscriber = subscriber;
    }

    // 使用另一个Subscriber对象作为背压和订阅列表的构造方法
    public Subscriber(Subscriber<?> subscriber, boolean shareSubscriptions) {
        this.subscriber = subscriber;
        if (shareSubscriptions) {
            subscriptions.shareWith(subscriber.subscriptions);
        }
    }

    // 将一个Subscription对象添加到订阅列表中
    public void add(Subscription s) {
        subscriptions.add(s);
    }

    // 取消订阅,取消订阅列表中的所有Subscription对象
    public void unsubscribe() {
        subscriptions.unsubscribe();
    }

    // 当Subscriber和Observable连接但Observable尚未开始发射数据或发送通知时调用的方法
    public void onStart() {
        // 默认情况下,不执行任何操作
    }

    // 设置请求通道,建立Observable和Subscriber之间的请求通道
    public void setProducer(Producer p) {
        long requested = this.requested;
        // 如果请求的数量已经设置,则向请求通道请求数据
        if (requested == NOT_SET) {
            return;
        }
        // 向请求通道请求指定数量的数据
        p.request(requested);
    }
}

subscribe()方法解析

以下为函数的核心部分

static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
    // 验证Subscriber和Observable是否合法
    if (subscriber == null) {
        throw new IllegalArgumentException("subscriber can not be null");
    }

    if (observable.onSubscribe == null) {
        throw new IllegalStateException("onSubscribe function can not be null.");
        /*
         * the subscribe function can also be overridden but generally that's not the appropriate approach
         * so I won't mention that in the exception
         */
    }

    // 调用Subscriber的onStart方法
    subscriber.onStart();

    // 如果subscriber没有被包装成SafeSubscriber,则进行包装
    if (!(subscriber instanceof SafeSubscriber)) {
        subscriber = new SafeSubscriber<T>(subscriber);
    }

    try {
        // 调用RxJavaHooks的onObservableStart方法,可以在这里进行拦截和装饰
        RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
        // 调用RxJavaHooks的onObservableReturn方法
        return RxJavaHooks.onObservableReturn(subscriber);
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        // 如果subscriber已经取消订阅,则调用RxJavaHooks的onError方法
        if (subscriber.isUnsubscribed()) {
            RxJavaHooks.onError(RxJavaHooks.onObservableError(e));
        } else {
            try {
                // 否则调用subscriber的onError方法
                subscriber.onError(RxJavaHooks.onObservableError(e));
            } catch (Throwable e2) {
                Exceptions.throwIfFatal(e2);
                // 如果onError方法执行出错,则抛出异常
                RuntimeException r = new OnErrorFailedException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
                RxJavaHooks.onObservableError(r);
                throw r; 
            }
        }
        // 返回取消订阅的Subscription对象
        return Subscriptions.unsubscribed();
    }
}

先对Subscriber和Observable进行合法性验证,然后调用Subscriber的onStart方法,接着判断是否需要对Subscriber进行包装,如果需要则进行包装。然后,调用RxJavaHooks的onObservableStart方法,可以在这里进行拦截和装饰,最后调用RxJavaHooks的onObservableReturn方法。如果出现异常,会根据情况进行处理,如果Subscriber已经取消订阅,则调用RxJavaHooks的onError方法,否则调用Subscriber的onError方法。最后返回取消订阅的Subscription对象。

笔者还没有看太深,只能暂时解析到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xoliu1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值