RxDataSource 中数据源是如何和绑定的-1

RxDataSource(3.0.1)版
RxDataSource 中数据源是如何和绑定的--绑定方法
其中最简单的tableView数据源就是一个无分组的数组,
例子A如下: 

        let items = Observable.just([
             "First Item",
             "Second Item",
             "Third Item"
         ])

         items
         .bind(to: tableView.rx.items) { (tableView, row, element) in
             let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
             cell.textLabel?.text = "\(element) @ row \(row)"
             return cell
         }
         .disposed(by: disposeBag)

这里可以看到items作为Observable<[String]>类型的数据源绑定到tableView上,根据后面闭包可以判定出,当tableview刷新时,肯定会调用后面返回cell的闭包,那么可以推断出,rx将这个闭包保存了起来,用到时就会调用。
    现在开始分析items.bind(to: tableView.rx.items)....... 是怎么个过程
    首先,不要被上面bind(to: )这个形式所迷惑了,其实他的原型是:(Observable+bind 这个文件中)

    public func bind<R1, R2>(to binder: (Self) -> (R1) -> R2, curriedArgument: R1) -> R2 {
         return binder(self)(curriedArgument)
    }

乍一看,很很复杂的样子,<R1, R2> 是泛型约束, R1 R2就是两种类型, 我们将它简化一下:

   func bind<R1, R2>(to binder: (Self) -> ((R1) -> R2), curriedArgument: R1) -> R2

-> func bind(binder: 参数A, curriedArgument: 参数B) -> 返回值C

其实就是一个两个参数的函数,不同的是参数A 是一个(Self) -> ((R1) -> R2) 这种类型的function,而,bind的参数B是R1类型的,这里要注意理解 参数A不是一个数,而是一个函数。而且是一个返回值也是函数的函数,即 f(a) -> ( f1(b) -> c ),bind函数执行,会执行传过来的参数A这个函数,而这个函数需要的参数又是 Self(调用者本身)
  现在再来看tableView.rx.items是什么鬼:(TableView+Rx 这个文件)

   public func items<S: Sequence, O: ObservableType>(_ source: O)
        -> (_ cellFactory: @escaping ((UITableView, Int, S.Iterator.Element) -> UITableViewCell))
        -> Disposable
        where O.E == S {
            return { cellFactory in
                let dataSource = RxTableViewReactiveArrayDataSourceSequenceWrapper<S>(cellFactory:   cellFactory)
                return self.items(dataSource: dataSource)(source)
            }
    }

一看这个函数,感觉更复杂,现在简化它:

   func items(_ source: O) -> ((cellFactory: xxx) -> Disposable)
->       f(a)             ->  (        f1(b)      ->  c         ) 

这么一看,他就是一个 f(a) -> ( f1(b) -> c) 类型的函数,正好符合bind(to: ) 这个函数的第一个函数要求,而bind(to: )第二个参数就是items .bind(to: tableView.rx.items)后面跟随的闭包
 func bind<R1, R2>(to binder: (Self) -> ((R1) -> R2), curriedArgument: R1) -> R2
现在binder这个参数有了,再看curriedArgument参数,他的类型是R1, 这里正好对应的事cellFactory东西,去tableView.rx.items函数定义的地方找cellFactory是什么类型,一看,他是一个函数,也就是一个闭包,所以,书写时将其写成了bind(to:)的尾随闭包形式,不用尾随闭包的形式:

        // 等价于:
        items.bind(to: tableView.rx.items, curriedArgument: { (tableView, row, element) in
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
            cell.textLabel?.text = "\(element) @ row \(row)"
            return cell
        }).disposed(by: bag)
        
        // 也等价于:
        typealias CellFactoryType = ((UITableView, Int, String) -> UITableViewCell)
        let cellFactory: CellFactoryType = { (tableView, row, element) in
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
            cell.textLabel?.text = "\(element) @ row \(row)"
            return cell
        }
        items.bind(to: tableView.rx.items, curriedArgument: cellFactory).disposed(by: bag)

这样,这个绑定结构方法就清楚了
 

注意:这里只是针对开头贴出来的例子A,TableView+Rx中 还有其他 items(..)类似方法,但是items(_ source: O)的参数传递并不和该例中一样,向bind(to)传递的并不是items(_ source: O)函数本身,而是items(_ source: O)的返回值

猜你喜欢

转载自my.oschina.net/dahuilang123/blog/1627404