十一、RxJava简析

RxJava有4个角色Observable、Observer、Subscriber和Suject,Observable和 Observer 通过subscribe方法实现订阅关系,Observable就可以在需要的时候通知Observer。

RxJava的使用

1,创建Observer(观察者)

它决定事件触发的时候有怎样的行为。

Subscriber subscriber = new Subscriber(){
    @Override
    public void onCompleted(){//事件队列完结,当不再有新的onNext触发时调用作为完成标志
    }
    @Override
    public void onError(){//在事件处理过程中出现异常时会触发同时队列终止
    }
    @Override
    public void onNext(){//将要处理的事件添加到事件队列
    }
    @Override
    public void onstart(){//在事件还未发送前调用可以做一些准备工作
    }
}

Observer是一个接口,Subscriber是在Observer上进行了扩展,也可以使用Observer创建观察者

Observer observer = new Observer(){
    @Override
    public void onCompleted(){}
    @Override
    public void onError(){}
    @Override
    public void onNext(){}
}

2,创建Observable(被观察者)

它决定了什么时候触发事件以及触发怎样的事件

Observable observable = Observable.create(new Observable.OnSubscribe(){
    @Override
    public void call(Subscriber subscriber){
    subscriber.onNext("123")//调用方法将事件添加到队列
    subscriber.onNext("456")
    subscriber.onCompleted()
    }
})

//简化写法利用just和from实现

Observable observable = Observable.just("123","456")//依次调用onNext方法和onCompleted方法。
String[] words = {"123","456"}
Observable observable = Observable.from(words)//依次调用onNext方法和onCompleted方法。

3,Subscribe(订阅)

将观察者和被观察者进行关联observable.subscribe(subscriber)

RxJava的Subject

Subject 既可以是一个 Observer 也可以是一个 Observerable,它是连接 Observer 和Observerable的桥梁。 因此,Subject可以被理解为Subject=Observable+Observer
1,PublishSubject:只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者,因此为了防止数据丢失可以在所有观察者都订阅完成后在发送数据。
2,BehaviorSubject:当Observer订阅BehaviorSubject时,它开始发射原始Observable最近发射的数据。如果此时还没有收到 任何数据,它会发射一个默认值,然后继续发射其他任何来自原始Observable的数据。如果原始的 Observable因为发生了一个错误而终止,BehaviorSubject将不会发射任何数据,但是会向Observer传递一个 异常通知。
3,ReplySubject:不管Observer何时订阅ReplaySubject,ReplaySubject均会发射所有来自原始Observable的数据给 Observer。不同类型的ReplaySubject用于限定Replay的范围,例如设定Buffer的具体大小,或者设定具体的时间范围。如果使用ReplaySubject作为Observer,注意不要在多个线程中调用onNext、onComplete 和onError方法。这可能会导致顺序错乱,并且违反了Observer规则。
4,AsyncSubject:当Observable完成时,AsyncSubject只会发射来自原始Observable的最后一个数据。如果原始的 Observable 因为发生了错误而终止,AsyncSubject 将不会发射任何数据,但是会向Observer传递一个异常通知。

RxJava操作符

包括defer、range、interval、start、repeat、timer

创建操作符

1,interval
创建一个按固定时间间隔发送整数序列的Observable,相当于定时器

Observable.interval(6,TimeUnit.SECONDS)//间隔6秒发送
                  .subscribe(new Action1(){
                  @Override
                  public void call(Long mLong){
                      //TODO
                      } 
                  })

2,range
创建发射指定范围整数序列的Observable,可以用于代替for循环,第一个参数为起始值且不小于0,第二个参数为终值,左闭右开。

Observable.range(0,8)
                  .subscribe((new Action1(){
                  @Override
                  public void call(Integer integer){
                      //TODO
                      } 
                  })

3,repeat
创建一个N次重复发射特定数据的Observable

Observable.range(0,8)
                   .repeat(3)//重复执行三次0-7循环
                  .subscribe((new Action1(){
                  @Override
                  public void call(Integer integer){
                      //TODO
                      } 
                  })

变换操作符

包括map、flatMap、cast、concatMap、flatMapIterable、buffer、groupBy
1,map
通过指定一个Func对象,将Obserable转换为一个新的Observable对象并发射,观察者将接收到新的Observable处理。例如利用map来处理域名更换:

final String Host = "http://baidu.com/"
Observable.just("image").map(new Func1(){
    @Override
    public String call(String s){
      return Host+s
    }
}).subscribe(new Action1(){
                  @Override
                  public void call(String s){
                      //TODO
                      } 
                  })

2,flatMap、cast
flatMap操作符将Observable发射的数据集合变换为Observable集合,然后将这些Observable发射的数据平坦的放入一个单独的Observable,cast操作符的作用是强制将Observable发射的所有数据转换为指定的类型。例如在多个请求接口前添加host:

final String Host="http://baidu.com"
Lsit list = new ArrayList<>()
list.add("image1")
list.add("image2")
list.add("image3")
//利用flatMap将list转换为Observable集合并再放入一个单独的Observable中发射,交叉执行不保证发射顺序。
Observable.from(list).flatMap(new Func1>(){
    @Override
    public Observable call(String s){
    return Observable.just(Host+s)
    }
//cast将Observable的数据转换为String类型
}).cast(String.class).subscribe(new Action1(){
                  @Override
                  public void call(String s){
                      //TODO
                      } 
                  })

3,concatMap
concatMap与flatMap操作符一致,解决了flatMap的交叉问题,提供了一种能够把发射值连续在一起的函数,而不合并他们。
4,flatMapIterable
可以将数据包装成Iterable,我们在Iterable中对数据进行处理。

Observable.just(1,2,3).flatMapIterable(new Func1>(){
    @Override
    publc Iterable call(Integer s){
    List mList = new ArrayList()
    mList.add(s+1)//对每个数都进行+1,输出为2,3,4
    return mList
    }
}).subscribe(new Action1(){
                  @Override
                  public void call(Integer integer){
                      //TODO
                      } 
                  }

5,buffer
将原Observable变换为一个新的Observable,新的Observable每次发射一组列表值而不是一个一个发射。和其类似的有window操作符,window操作符发射的是Observable而不是数据列表

Observable.just(1,2,3,4,5,6)
                  .buffer(3)//缓存容量为3,输出为两组每组3个数分别输出
                  .subscribe(new Action1>(){
                  @Override
                  public void call(List integers){
                      //TODO
                      } 
                  })

6,groupBy
用于元素分组,将原Observable变换为一个发射Observable的新的分组后的Observable,每一个新的Observable都是发射一组指定数据。

Observable> groupObservable 
= Observable.just(obj1,obj2,obj3)
                     .groupBy(new Func1){
                     @Override
                     public String call(Object obj){
                      return obj.value//用于确定分组的参数
                     }
                     }
//对分组后的数据输出
Observable.concat(groupObservable).subscribe(new Action1(){
                  @Override
                  public void call(Object obj){
                      //TODO
                      } 
                  })
 
 

过滤操作符

包括filter、elementAt、distinct、skip、take、skipLast、takeLast、ignoreElements、throttleFirst、sample、debounce、throttleWithTimeout

组合操作符

包括startWith、merge、concat、zip、combineLastest、join、switch

辅助操作符

包括delay、DO、subscribeOn、observeOn、timeout、materialize、dematerialize、timeInterval、timestamp、to

错误处理操作符

包括catch、retry

布尔操作符

包括all、contains、isEmpty、exists、sequenceEqual

条件操作符

包括amb、defaultIfEmpty、skipUntil、skipWhile、takeUnit、takeWhile

转换操作符

包括toList、toSortedList、toMap、toMultiMap、getIterator、nest

RxJava线程控制

如果不设置线程,默认为在subscribe方法的线程上进行回调,设置线程需要用到Scheduler
Scheduler.immediate():在当前线程运行
Scheduler.newThread():总是启用新线程
Scheduler.io():I/O操作使用的Scheduler,和newThread类似,区别在于io内部实现的是一个无数量上限的线程池,可以重用空闲线程比newThread更有效率。
Scheduler.computation():计算使用的模式,使用固定线程池大小为cpu核数,不要进行I/O操作其等待时间会浪费cpu资源。
Scheduler.trampoline():在当前线程非立即执行使用,可以将任务加入队列然后按顺序运行。
RxAndroid提供的常用的Scheduler
AndroidSchedulers.mainThread():指定操作在主线程运行。
在RxJava中用subscribeOn和observeOn操作符来控制线程。

源码解析

1,RxJava订阅过程。
查看一段RxJava的基本使用代码。
Observable.create(new Observable.OnSubscribe)...
.subscribe(new Subscriber)...
查看create方法的定义

public static  Observable create(OnSubscribe f){
    return new Observable(hook.onCreate(f))
}

可以看出在create方法中创建了Observable对象并返回,hook表示的是RxJavaObservableExecutionHook。查看他的onCreate方法定义

public  OnSubscribe onCreate(OnSubscribe f){
  return f
}

在RxJavaObservableExecutionHook的onCreate方法中只是返回了传入得被观察者对象。
查看Observable的构造方法

protected Observable(OnSubscribe f){
  this.onSubscribe = f//将前边构建的Observable对象赋值给了onSubscribe
}

之后调用subscribe方法完成订阅,查看Observable的subscrbie方法

static  Subscription subscribe(Subscriber subscriber,Observable observble)
...
subscriber.onStart()
if(!(subscriber instancefo SafeSubscriber)){//进行类型检查,如果不是进行封装
//SafeSubscriber继承自Subscriber,在 onCompleted和onError方法调用时不会再调用onNext,且保证onCompleted和onError方法只有一个执行
    subscriber = new SafeSubscriber(subscriber)
}
try{
    hook.onSubscribeStrt(observable, observable.onSubscribe).call(subscriber)
    return hook.onSubscribeReturn(subscriber)
}catch(Throwable e){
    ...
    return Subscriptions.unsubscribed()
}

查看hook的onSubscribeStart方法可以发现是调用OnSubscribe.call(subscriber)来完成订阅的

public  OnSubscribe onSubscribeStart(Observable observable,final OnSubscribe onSubscribe){
    return onSubscribe
}

2,RxJava的变换过程
前边说过map操作符会将源Observable转换为一个新的Observable,查看map方法

public final  Observable map(Func1func){
//OperatorMap实现了Operator接口的call方法,且在call方法中创建了MapSubscriber并返回
    return lift(new OperatorMap(func))
}

lift 方法返回一个新建的 Observable 对象ob2,并传入了一个 OnSubscribeLift对象记为on2,他的构造函数中需要两个参数为onSubscribe 和 operator(OperatorMap),在OnSubscribeLift构造方法中会拿到开始creat创建的Observable(前边提过的onSubscribe变量on1),在其call方法中调用hook.onLift(operator).call(o)方法即调用的是用OperatorMap的call方法返回MapSubscriber记为sub2,继续执行可理解为on1.call(sub2)完成订阅。在map方法后调用的subscribe方法传入Subscriber类型参数标记为sub1。
subscribe方法前面讲过,它会调用:hook.onSubscribeStart(observable,observable.onSubscribe).call(subscriber) 因为此前调用过map操作符,所以这里传入的observable.onSubscribe指的是on2。分析RxJava的订阅过程,onSubscribeStart方法会返回onSubscribe,也就是on2,相当于on2.call(sub1),on2指的是 OnSubscribeLift,在on1的call中会调用sub2的onNext查看MapSubscriber的onNext方法中调用了actual.onNext(result)方法,actual指的是sub1从而完成了变换过程。


map转换图

3,RxJava的线程切换过程
线程切换主要用到了subscribeOn和observeOn两个方法,一个决定了被观察者执行线程,一个决定了观察者运行线程。

subscribeOn方法定义:

public final Observable subscribeOn(Scheduler shceduler){
  if(this instanceof ScalarSynchronousObservable){
    return ((ScalarSynchronousObservable)this).scalarScheduleOn(scheduler)
  }
  return create(new OperatorSubscribeOn(this,scheduler))
}

上面代码create 方法仍旧是生成一个新的 Observable,并传入一个OperatorSubscribeOn 类。 OperatorSubscribeOn 需要传入两个参数:第一个参数 this,指的是我们最先创建的Observable,第二个参数是一个Scheduler。在OperatorSubcribeOn的call方法中调用Scheduler的createWorker方法会创建Worker然后调用它的schedule方法,Worker是线程处理的代理执行者。
选取查看Schedulers.newThread()代码:

poublic static Scheduler newThread(){
  return getInstance().newThreadSchedulere
}

Scheduler 是一个单例类,其返回自身的 newThreadScheduler 属性。这个属性最终指的是 NewThreadScheduler。

public final class NewThreadScheduler extends Scheduler{
  private final ThreadFactory threadFactory
  public NewThreadScheduler(ThreadFactory threadFactory){
    this.threadFactory = threadFactory
  }
  @Override
   public Worker createeWorker(){
      reurn new NewThreadWorker(threadFactory)
   } 
}

此前在 OperatorSubscribeOn 中调用了 Scheduler 的 createWorker 方法,其实就是调用 NewThreadScheduler 的createWorker方法。NewThreadWorker中使用了ScheduledThreadPool线程池。OperatorSubscribeOn中调用了 Worker 的 schedule 方法,而 Worker 指的是NewThreadWorker

public Subscription schedule(final Action0 action,long delayTime,TimeUnit unit){
  if(isUnsubscribed){
    return Subscriptions.unsubscribbed()
  }
  return scheduleActual(action,delayTime,unit)
}
//scheduleActual方法
public ScheduledAction scheduleActual(final Action0 action,long delayTime,TimeUnit unit){
  Action0 decoratedAction = schedulersHook.onSchedule(action)
  ScheduledAction run = new ScheduledAction(decoratedAction)
  Futuref
  if(delayTime<=0){
     f=executor.submit(run)
  }else{
    f = executor.schedule(run,delayTime,unit)
  }
  run.add(f)
  return run
}

可以看到最终线程切换的处理均由线程池处理。

observeOn方法定义

public final Observable observeOn(Scheduler scheduler,boolean delayError,int bufferSize){
  if(this instanceof ScalarSynchronousObservable){  
    return ((ScalarSynchronousObservablethis).scalarScheduleOn(scheduler)
  }
  return lift(new OperatorObserveOn(scheduler,delayError,bufferSize)
}

OperatorObserveOn和此前讲过的OperatorMap类似在其call方法中创建了ObserveOnSubscriber

ObserveOnSubscriber parent = new ObserveOnSubscriber(scheduler,child,delayError,bufferSize)
parent.init()
return parent

ObserveOnSubscriber是Subscriber的子类,在其onNext,onCompleted,onError方法中都调用了schedule方法。

protected void schedule(){
    if(counter.getAndIncrement() == 0){
        recursiveScheduler.schedule(this)
    }
}

recursiveScheduler是一个Worker,this指的是ObserveOnSubscriber,这意味着ObserveOnSubscriber的 onNext方法都被切换到recursiveScheduler的线程做处理,从而达到线程切换的目的。

你可能感兴趣的:(十一、RxJava简析)