yuhanle / blogbag

我会不断更新这个仓库中的文章
https://latehorse.github.io/
14 stars 1 forks source link

Use RxFlow Coordinator #10

Open yuhanle opened 4 years ago

yuhanle commented 4 years ago

RxFlow

借用官方的描述来说,RxFlow 是一个基于反应流协调器模式的 iOS 应用程序导航框架。

image

Flow

导航的抽象,负责持有 root 和执行 navigate 操作

/// A Flow defines a clear navigation area. Combined to a Step it leads to a navigation action
public protocol Flow: class, Presentable, Synchronizable {

    /// the Presentable on which rely the navigation inside this Flow. This method must always give the same instance
    var root: Presentable { get }

    /// Resolves FlowContributors according to the Step, in the context of this very Flow
    ///
    /// - Parameters:
    ///   - step: the Step emitted by one of the Steppers declared in the Flow
    /// - Returns: the FlowContributors matching the Step. These FlowContributors determines the next navigation steps (Presentables to display / Steppers to listen)
    func navigate (to step: Step) -> FlowContributors
}

在其 extension 中,flowReadySubject 返回是否可以执行 Flow,并包装成 Single 命名为 rxFlowReady。

FlowContributor

提供 Flow 的抽象,可以做到派发 Flow

/// A FlowContributor describes the next thing that will contribute to a Flow.
///
/// - contribute: the given stepper will emit steps (according to lifecycle of the given presentable) that will contribute to the current Flow
/// - forwardToCurrentFlow: the given step will be forwarded to the current flow
/// - forwardToParentFlow: the given step will be forwarded to the parent flow
public enum FlowContributor {
    /// the given stepper will emit steps, according to lifecycle of the given presentable, that will contribute to the current Flow
    case contribute(withNextPresentable: Presentable, withNextStepper: Stepper)
    /// the "withStep" step will be forwarded to the current flow
    case forwardToCurrentFlow(withStep: Step)
    /// the "withStep" step will be forwarded to the parent flow
    case forwardToParentFlow(withStep: Step)

    /// Shortcut static func that returns a .contribute(withNextPresentable: _, withNextStepper: _)
    /// in case we have a single actor that is a Presentable and also a Stepper
    ///
    /// - Parameter nextPresentableAndStepper
    /// - Returns: .contribute(withNextPresentable: withNext, withNextStepper: withNext)
    public static func contribute(withNext nextPresentableAndStepper: Presentable & Stepper) -> FlowContributor {
        return .contribute(withNextPresentable: nextPresentableAndStepper, withNextStepper: nextPresentableAndStepper)
    }
}

FlowCoordinator

RxFlow 的核心实现,协调处理 Flow 的流转,通过 coordinate 的 API 执行 Flow

Stepper

public protocol Stepper {

    /// the relay used to emit steps inside this Stepper
    var steps: PublishRelay<Step> { get }

    /// the initial step that will be emitted when listening to this Stepper
    var initialStep: Step { get }

    /// function called when stepper is listened by the FlowCoordinator
    func readyToEmitSteps ()
}

默认是 NoneStep,readyToEmitSteps 是空实现

OneStepper

一个简单的 step,大部分场景可以直接使用

DefaultStepper

默认是 RxFlowStep.home

CompositeStepper

复杂场景下的 Step,合并多个 step,把初始 step 和下一个 step 关联起来

public func readyToEmitSteps() {

        let initialSteps = Observable<Step>.from(self.innerSteppers.map { $0.initialStep })

        let nextSteps = Observable<Step>
            .merge(self.innerSteppers.map { $0.steps.asObservable() })

        initialSteps
            .concat(nextSteps)
            .bind(to: self.steps)
            .disposed(by: self.disposeBag)
}

NoneStepper

不触发任何 step

Usage

根据业务生命周期,遵循 Flow 协议构造对应的 Flow,比如 APP 生命周期的 APPFlow,登录相关的 LoginFLow,设置的 SettingFLow 等。

多个 Flow 共享一个或多个 Step (具体看业务场景,独立业务内部可以自由约定) 约定,对外约定 GlobalStep,业务模块化粒度适中,尽量保证一个业务只有一个 GlobalStep 便于维护。

具体使用可以参考 RxFlowDemo 示例

执行 Step 的两种方式

处理原则

接口

LingoFlowAvailable

缺陷

参考文档