RxJava2使用解析

RxJava2

前提:
android常用基础异步工具:AsycTask,规范使用时需要继承重写作为abstract类
handler,绑定-sendMessgae-handleMessage
当需求任务数量增加,代码逐渐变混乱和繁杂
Rxjava,能简洁的实现异步操作,响应式编程,代码可读性强

认识

观察者模式

主要理解因素:observable(被观察者)、subscribe(订阅)、observer(观察者)
经典例子概念理解:处理点击按钮
点击,触发按钮产生onClick事件,响应时需要onClickListener来实现点击效果。事件发生对象(按钮)和监听处理事件对象(onClickListener)之间,通过setOnclickListener建立两者监听关系
同理,通过订阅建立被观察者和观察者之间的响应关系

基础使用

创建被观察者

常用创建操作符:

Observable.just("t","e","s","t")    //just() : item最多接收10个参数

Observable.fromArray(new String[]{"test","hello"})  //fromArray(Iterable)
//直接数据就是要传递的事件本身

Observable.create(new ObservableOnSubscribe<Object>() {

            @Override
            public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                //产生事件
            }
        })
        
 创建操作符操作后,返回Observable实例

创建观察者

观察者 : Observer 和 Consumer
public interface Observer<T> {

    /**
     * @since 2.0
     * 给予当前订阅事件实例给观察者使用,用于取消订阅
     */
    void onSubscribe(@NonNull Disposable d);

    /**
     * @param t
     *          the item emitted by the Observable
     *  传递item,0或者多次被调用,onError或OnComplete后不再调用
     */
    void onNext(@NonNull T t);

    /**
     * @param e
     *          the exception encountered by the Observable
     */
    void onError(@NonNull Throwable e);

    /**
     * The {@link Observable} will not call this method if it calls {@link #onError}.
     */
    void onComplete();

}

public interface Consumer<T> {
    /**
     * Consume the given value.
     * @param t the value
     * @throws Exception on error
     */
    void accept(T t) throws Exception;
}

订阅 Subscribe

Observable.subscribe(Observer) //建立关系
 Observable<String> observable = Observable.fromArray("t", "e", "s", "t");
    //Consumer使用  
  observable.subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.i(TAG, "Consumer.accept :" + s);
            }
        });

  //Observer使用
  observable.subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.i(TAG, "onSubscribe");
            }

            @Override
            public void onNext(String s) {
                Log.i(TAG, s);
            }

            @Override
            public void onError(Throwable e) {
                Log.i(TAG, "onError");
            }

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete");
            }
        });

效果log:
Consumer.accept :t
Consumer.accept :e
Consumer.accept : s
Consumer.accept :t
onSubscribe
t
e
s
t
onComplete

源码部分

//当前基础使用情况下,使用Observable作为被观察者
//而观察者有Observer(onNext、onError、OnSubscibe、onComplete) vs Consumer(accept)
//从源码查看使用的区别:

   public final Disposable subscribe(Consumer<? super T> onNext) {
        return subscribe(onNext, Functions.ON_ERROR_MISSING, Functions.EMPTY_ACTION, Functions.emptyConsumer());
}

// 结合来看,订阅事件的观察者实际需要Observer4个方法处理实现的,而使用consumer可以让我们只需关注处理传递得到的数据,系统会创建空方法实例去补充

//订阅方法接收的其他参数方法:

  public final Disposable subscribe(Consumer<? super T> onNext
                     , Consumer<? super Throwable> onError) {
        return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer());
    }

//可见observer的部分方法可用consumer实现,非强制性实现所有接口

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,Action onComplete, Consumer<? super Disposable> onSubscribe) {
        ObjectHelper.requireNonNull(onNext, "onNext is null");
        ObjectHelper.requireNonNull(onError, "onError is null");
        ObjectHelper.requireNonNull(onComplete, "onComplete is null");
        ObjectHelper.requireNonNull(onSubscribe, "onSubscribe is null");
        //内部将consumer整合成Observer
        LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);

        subscribe(ls);*

        return ls;
    }

consumer和observer的区别

由此部分代码得出:
Observer是完整观察者接口。
consumer内部只有一个接口,可以实现observer的某一方法(除onComplete使用Action)
可查看LambdaObserver将consumer组合成Observer使用
Disposable subscribe(consumer)
void subscribe(observer)

订阅事件的流程
//观察者订阅的主要位置   

public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");//判空
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);//hook,返回本身或处理后

            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");

            subscribeActual(observer);* 
        } catch (NullPointerException e) {
            throw e;
        } catch (Throwable e) {
          ...
        }
    }

查看当前observable具体的subscribeActual实现:

ObservableCreate<T>内部代码:

@Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        //使用observer创建emitter,emitter间接替代观察者被被观察者调用传递,更安全
        observer.onSubscribe(parent);//传递前的准备

        try {
            source.subscribe(parent);//执行被观察者唯一的方法,被观察者开始行动
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }
*******由此方法看出,被观察者在订阅方法执行时才开始传递事件*********

从demo看,在subscribe()调用emitter的传递方法,而Emitter接口与Observer相似拥有onNext、onError、onComplete;实际在内部封装observer的具体方法

 CreateEmitter内部代码:
       @Override
        public void onNext(T t) {
            if (t == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
            if (!isDisposed()) {
                observer.onNext(t);
            }
        }

    @Override
        public void onError(Throwable t) {
            if (!tryOnError(t)) {
                RxJavaPlugins.onError(t);
            }
        }
 //由代码可见,在真正调用observer处理前,会先判断订阅是否正常

emitter用于替换观察者,用作被Observable调用
在这里插入图片描述

线程调度器 Scheduler

RxJava的出现,目的在于对异步操作用了更简洁的方式。而scheduler就是用于给此订阅事件调度切换线程的。
项目中,常等待耗时请求结果显示ui的需求。
subscribeOn(scheduler) : 指定被观察者产生事件操作所处线程
observeOn(scheduler) : 指定观察者处理事件操作所处线程
RxJava 已经内置了几个 Scheduler ,它们已经适合大多数的使用场景:

  • **Schedulers.immediate() **: 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
  • Schedulers.newThread() : 总是启用新线程,并在新线程执行操作。
  • _Schedulers.io() _: I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
  • Schedulers.computation() : 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
  • 另外, Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。

项目常用被观察者处于io scheduler进行耗时操作,观察者在mainThread将耗时操作的结果进行ui展示

更多使用

操作符

Observable是链式调用的,可通过调用操作符对被观察者事件进行直接操作
操作符操作后,返回处理后的Observable继续往下传递

doc操作符分类简介:http://reactivex.io/documentation/operators.html

此处以map操作符展开分析:

demo解析

在这里插入图片描述

Log:
receive integer is 0
receive integer is 1
receive integer is 2
receive integer is 0

Observable传递的String类型元素通过map操作符转换规则处理变更为Integer。
转换逻辑由Function.apply实现,处理完成返回Observable对象继续往下传递。
在这里插入图片描述

源码
   public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
       ...判空
        return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }// 返回 ObservableMap

由此可知,Observable操作后返回仍为Observable
那么操作符处理后的Observable有什么不同之处呢?

  1. ObservableMap 没有直接继承Observable。而是继承抽象类**AbstractObservableWithUpstream_ which extends Observable**_ .抽象类实现保存构建函数传入的Observable实例
abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> 
                                      implements HasUpstreamObservableSource<T> {

    protected final ObservableSource<T> source;//可观察的资源
    AbstractObservableWithUpstream(ObservableSource<T> source) {
        this.source = source;
    }
    @Override
    public final ObservableSource<T> source() {
        return source;
    }
}
  1. ObservableMap继承**AbstractObservableWithUpstream**,才具体实现Observable.subscibeActual()。而subscibeActual()不做传递事件工作,而是将当前Observer和操作符规则Function封装成new Observer并前一个Observable。
  @Override
    public void subscribeActual(Observer<? super U> t) {
        source.subscribe(new MapObserver<T, U>(t, function));
    }

因此理解:通过非创建操作符创建的Observable作为Special Observable。被订阅时,不实现事件产生传递,作为中间商将操作符转换规则和当前Observer封装成new Observer 订阅处理前一个Observable。

流程理解

此流程为抽象概念理解,具体请查阅源码在这里插入图片描述

  • 首先:先从上往下看,树店存在而木店存在,木店存在而纸店存在。这是被订阅者的创建前提
  • 过程理解:

树店相当于传递事件的Observable
木店、纸店相当于经过操作符操作后的Special Observable
ps : 这条街上,木店的创建是由于树店的存在而创建的,纸店同理。
进货商都为Observer,订货购买操作理解为订阅。
理解真正的客人,只是最初买纸的进货商,货物到他手上才是真正使用的。
此处使用方法教程理解为,店铺对于购买者给与的使用方法,理解为Function。(开店时已有合作协议,以已拿到使用方法为前提)

  1. 进货商A对纸店订货购买纸,产生了订阅事件,激发纸店派工人带着制纸方法进货。
  2. 纸店工人作为买木的进货商,向木店订货购买。激发木店派工人带着制木方法到树店进货。
  3. 木店工人作为买树进货商向树店订货购买,等货制木。
  4. 树店收到订货,将店内的树搬出来,把树传给木店工人。
  5. 木店工人收到树,按照制木方法,将树制造成木,传递给纸店工人。
  6. 纸店工人收到木后,按照制纸方法,将木造成树,传递给进货商A。
  7. 完成交易。

查看各类操作符,subscribeActual实现逻辑与当前解析map流程理解相同。因此以是否继承AbstractObservableWithUpstream作为判断Special Observable的要素

背压 BackPressure

来源

以subscribe()方法为分界,前面的操作作为被观察者发生事件的源头称为上游。后续的操作作于处理事件称为下游。
发生前提:上游和下游是异步操作,上游传递事件速度>下游处理事件速度,那么事件就会存放缓存池中。那么当缓存池中存放的事件越存越多,超过bufferSize(默认128),就会出现内存溢出。这就是背压问题。
Observable没有作背压问题处理,所以出现Flowable。
Flowable作为被观察者,通过设置背压策略来避免背压问题。
Flowable传递的数据流,以及对数据加工处理的各操作符都添加了背压支持,附加了额外的逻辑,其运行效率要比 Observable 低得多,应酌情考虑条件谨慎使用。

Flowable

基本用法与Observable相似,增加了背压策略指定:

1.在create创建操作符中:指定
public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
        ObjectHelper.requireNonNull(source, "source is null");
        ObjectHelper.requireNonNull(mode, "mode is null");
        return RxJavaPlugins.onAssembly(new FlowableCreate<T>(source, mode));
    }

2.或使用操作符指定:
Flowable.just("t", "e", "s", "t")
                .onBackpressureBuffer()
                .subscribe();

BackpressureStrategy 背压策略

public enum BackpressureStrategy {
    MISSING,
    ERROR,
    BUFFER,
    DROP,
    LATEST
}
  • MISSING:传递的事件不缓存,不丢掉。直接传递到下游,若出现背压问题,直接抛出异常。
  • ERROR:当缓存池中的数据超限,不能再插入缓存,则会抛出 MissingBackpressureException 异常
  • BUFFER:默认策略。没有限制缓池大小,不限制插入事件数据。不会抛出异常,但会导致OOM。
  • DROP:若异步缓存池满了,会直接丢掉将要放入缓存池中的数据。
  • LATEST:与DROP相似,不同的是,不管缓存池的状态如何,LATEST都会将最后一条数据强行放入缓存池中。

具体实现源码可在FlowableCreate查看策略不同而创建的Emitter处理

Subscriber

注意,当被观察者使用Flowable时,观察者需要使用Subsciber配合使用。与Observer使用方法类似,不同在于

.subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        s.request(10);//说明下游有效接收上游事件传递总量
                    }

Subscription.request()必须调用,否则下游不响应上游的事件传递。同时若上游传递超过num的设定,下游也不再响应。

Disposable

使用Disposable实例表示整个订阅事件。
disposable 出现在:

Disposable disposable = Obervable.subscibe(Consumer)
    
...
   .subscribe(new Observer<Object>{
    
      public void onSubscribe(Dispoable d){
         disposable =  d
      }
   })

内部实现两个接口 :
void dispose() : 调用以取消当前订阅事件,释放资源。
boolean isDisposed() : 判断当前订阅事件是否已取消,常用于在订阅流程中作安全判断,未取消才继续执行。
项目中,常用CompositeDisposable 管理订阅事件。

管理

有订阅事件发生,CompositeDisposable 将其加入管理

CompositeDisposable.add(dispoable)

当关闭当前调用RxJava开启订阅事件的容器时,可能会存在订阅事件未完成或订阅事件未被取消释放资源,因此在容器的生命周期要进行资源释放:

   @Override
    public void onDestroy() {
        if (mCompositeDisposable != null && mCompositeDisposable.size() > 0) {
            mCompositeDisposable.clear();
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RxJava中的flatMap操作符是一个非常常用的操作符,它可以将一个Observable发射的事件序列转换成多个Observables,然后将这些Observables发射的事件序列合并后再发射出去。 下面是flatMap操作符的源码解析: ```java public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) { ObjectHelper.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMap<>(this, mapper, false, Integer.MAX_VALUE, bufferSize())); } ``` 可以看到,flatMap操作符的实现是通过创建一个ObservableFlatMap对象来完成的。其中,mapper参数表示将原始Observable发射的事件转换成的新Observable,它是一个Function类型的参数,即接受一个T类型的参数并返回一个ObservableSource类型的结果。 ObservableFlatMap的构造函数如下所示: ```java ObservableFlatMap(ObservableSource<T> source, Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors, int maxConcurrency, int bufferSize) { this.source = source; this.mapper = mapper; this.delayErrors = delayErrors; this.maxConcurrency = maxConcurrency; this.bufferSize = bufferSize; } ``` ObservableFlatMap的核心实现是在subscribeActual方法中完成的: ```java @Override public void subscribeActual(Observer<? super R> observer) { if (ObservableScalarXMap.tryScalarXMapSubscribe(source, observer, mapper)) { return; } source.subscribe(new FlatMapObserver<>(observer, mapper, delayErrors, maxConcurrency, bufferSize)); } ``` 在subscribeActual方法中,首先判断源Observable是否可以直接转换为ObservableScalarXMap,如果可以的话直接进行转换,否则创建一个FlatMapObserver对象并进行订阅。 FlatMapObserver是flatMap的核心实现类,它实现了Observer接口,并且在接收到源Observable发射的事件时,会先将事件转换成新的Observable,然后将新Observable的发射事件序列合并到一个新的Observable中,最后再将新的Observable发射出去。 ```java static final class FlatMapObserver<T, R> extends AtomicInteger implements Observer<T>, Disposable { // ... @Override public void onNext(T t) { ObservableSource<? extends R> o; try { o = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource"); } catch (Throwable e) { Exceptions.throwIfFatal(e); upstream.dispose(); onError(e); return; } if (cancelled) { return; } if (maxConcurrency != Integer.MAX_VALUE) { synchronized (this) { if (wip == maxConcurrency) { queue.offer(t); return; } wip++; } } o.subscribe(new InnerObserver(inner, delayErrors, this)); } // ... } ``` 在FlatMapObserver的onNext方法中,首先调用mapper将源Observable发射的事件转换成新的Observable,并进行非空检查。然后判断当前的并发度是否达到了最大值,如果达到了最大值,就将源Observable发射的事件放到队列中。否则,就将并发度加1,并订阅新Observable。 InnerObserver是FlatMapObserver的内部类,它实现了Observer接口,并在接收到来自新Observable的发射事件序列时,将它们合并到一个新的Observable中,并将新的Observable发射出去。 ```java static final class InnerObserver<R> implements Observer<R> { // ... @Override public void onNext(R t) { if (done) { return; } inner.onNext(t); } // ... } ``` 当所有的新Observable都完成后,FlatMapObserver会调用onComplete方法通知观察者。如果发生了异常,FlatMapObserver会调用onError方法通知观察者。同时,FlatMapObserver还实现了Disposable接口,可以通过dispose方法取消订阅。 综上所述,flatMap操作符的实现是比较复杂的,它通过创建ObservableFlatMap对象,并在subscribeActual方法中创建FlatMapObserver对象来完成转换操作。在FlatMapObserver中,它还需要实现对新Observable的订阅以及将新Observable发射的事件合并到一个新的Observable中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值