ReactorKit 粗略源码分析

ReactorKit作为RxSwift的框架之一,如文档描述结合了Flux思想,行为单向性,Reactor只进行行为处理和状态改变通知。框架的主要成分为ActionStateMutation(对客户环境不可见)、func mutate(Action -> Mutation)、func reduce(通过Mutation更新State),它们都是由Reactor类进行组合关联。注意:客户环境的定义在上篇RxFeedback 粗略源码分析可见。下文中的大部分客服环境可以看做为View实体(··View 和 ··ViewController在框架内都指代为View实体)或者ViewController。框架内大部分成员读写都是通过AssociatedObject方式进行处理。 现在从源码说起。

首先,要使用ReactorKit除了创建一个对应的Reactor类外,还需要实现View协议的View实体View协议,如下:

public protocol View: class, AssociatedObjectStore {
  associatedtype Reactor: _Reactor

  var disposeBag: DisposeBag { get set }
  var reactor: Reactor? { get set }

  func bind(reactor: Reactor)
}

,定义两个成员和一个方法,后续将分析调用过程。框架提供了另一个协议StoryboardView(继承了协议_ObjCStoryboardViewView)使ViewControllerviewDidLoad方法中调用View协议的方法func bind(reactor: Reactor)。在"ReactorKitRuntime.m"文件中,NSObject加载时通过Runtime交换ViewControllerviewDidLoad方法,并在中间执行ViewController_reactorkit_performBinding方法,在@objc func _reactorkit_performBinding()中调用了_ObjCStoryboardView协议方法performBinding,在StoryboardView的扩展中的performBinding方法调用了View的协议方法self.bind(reactor: reactor),让ViewControllerReactor进行处理。

extension OSViewController {
  @objc func _reactorkit_performBinding() {
    (self as? _ObjCStoryboardView)?.performBinding()
  }
}

.

下面具体分析self.bind(reactor: reactor)背后的逻辑。在客户环境中都是通过如下代码建立关联:

    //Action
    ···btn.rx.tap
      .map { Reactor.Action. ··· }
      .bind(to: reactor.action)
      .disposed(by: disposeBag)
    // State
    reactor.state.map { ··· }
      .distinctUntilChanged()
      .bind(to: ···)
      .disposed(by: disposeBag)

点击事件通过map处理,通知Action事件给reactor.action序列。reactor.action的执行,在Reactor基类里通过var action属性获取到Action序列_action前,先进行了State序列_state的处理 _ = self._state,如果不存在则创建,创建的代码为self.createStateStream()。注意在createStateStream函数中获取Action序列是直接通过self._action(同样不存在进行创建,但只是通过默认构造函数.init()),避免通过self.action造成循环引用。下面来看看框架的关联核心createStateStream

public func createStateStream() -> Observable {
    let action = self._action.asObservable()
    let transformedAction = self.transform(action: action)
    let mutation = transformedAction
      .flatMap { [weak self] action -> Observable in
        guard let `self` = self else { return .empty() }
        return self.mutate(action: action).catchError { _ in .empty() }
      }
    let transformedMutation = self.transform(mutation: mutation)
    let state = transformedMutation
      .scan(self.initialState) { [weak self] state, mutation -> State in
        guard let `self` = self else { return state }
        return self.reduce(state: state, mutation: mutation)
      }
      .catchError { _ in .empty() }
      .startWith(self.initialState)
      .observeOn(MainScheduler.instance)
    let transformedState = self.transform(state: state)
      .do(onNext: { [weak self] state in
        self?.currentState = state
      })
      .replay(1)
    transformedState.connect().disposed(by: self.disposeBag)
    return transformedState
  }
  • 首先获取Action可观察序列action
  • action通过transform进行装换后,通过flatMapAction传入到self.mutate方法,转换为Mutation序列mutation
  • mutation通过transform进行装换后,进行scan操作符将StateMutation传入到self.reduce方法,装换为State序列state
  • state通过transform进行装换后,进行do操作更新当前状态currentState,在进行replay、connect操作,此时State的序列创建完成,赋给_state

_ = self._state则执行完毕,由于在createStateStream_action已经创建,后面直接返回值。 到此,客户环境中的reactor.action执行完毕。如果客户环境先执行的reactor.state.···的调用,则直接调用的createStateStream方法,Action序列self._action也同样被创建。

到此,Reactor的状态序列和行为序列就创建完成,在客户环境func bind(reactor: ···)方法中,就可以接收状态的改变和发起行为。在Reactor的实现类中的func mutatefunc reduce方法,处理从ActionMutation,再到State的转变。

另外,ActionSubject作为Action的观察者,也是Action的可观察序列。在客户环境通过事件发出Action,被ActionSubject监听到后,通过可观察序列的多次操作转换State的可观察序列, 最后通知到State的观察者。
ActionSubject作为观察者的代码:

  public func on(_ event: Event) {
    ···
    if case .next = event {
      self.observers.values.forEach {
        $0(event)
        }
    }
   ···
  }

,作为可观察序列被订阅的代码:

  public func subscribe(_ observer: O) -> Disposable where O.E == Element {
    
    ···
    let key = self.nextKey
    self.nextKey += 1
    self.observers[key] = observer.on
    ···
  }

,订阅者订阅ActionSubject,它保存了订阅者的被通知方法observer.on。当ActionSubject自身被通知发生了Action序列事件时,只在事件行为为.next时,才通知自己的订阅者有新的事件行为发生。

你可能感兴趣的:(ReactorKit 粗略源码分析)