稀有猿诉

十年磨一剑,历炼出锋芒,说话千百句,不如码二行。

Understanding RxJava

RxJava不仅仅是一个函数库,它是响应式编程范式的一个JVM实现,所以准确的来说RxJava是一种编程范式。而且它的学习曲线非常之陡峭,必须充分理解它背后的编程思想,才能真正算使用它。

理解ReactiveExtensions

Rx的核心思想是两个方面,一是数据流,把一切看成数据流,只需要关心数据来了如何响应;二是异步,也就是说不会立马得到结果。需要做的就是搭建好处理数据流的管道和定义数据最终的响应方式,其他的交给Rx内部去处理。

Functional Programming

函数式编程是以函数为核心来构建程序,通过不同的函数的不同形式的组合来作为主要解决方案。 这是从另外的角度来看待问题。程序如果只写出来,做了静态意义上的区分 是没有意义的,程序必须 运行起来 才有价值。函数式编程更加注重程序的运行,程序运行的基本单元是什么?函数,任何程序都是从一个叫主函数开始,一层一层的调用,所以函数式编程思考问题时的基本单元是函数,至于数据则以参数形式在函数之间传递。以函数为核心带来的好处是,让异步变得容易 。

Reactive Programming

大部分编程思想是以控制流为核心(flow of control),而响应式核心是数据流(data flow)为核心,再加上异步。并不关心程序的控制,只关心数据如何流动,以及当数据来了时如何响应,以及对数据如何处理。

Functional Reactive Programming

综合函数式和响应式,主要还是数据流,只不过以函数式的方式来处理数据流,并且都是异步形式。

什么是异步

这个也要理解 一下。异步与同步是一个程序执行顺序上的概念,而非具体的编程技术。同步,也就是说一坨一坨的代码是自上而下的执行,或者说函数是按照书写时的调用顺序,顺序 的执行。最明显的就是调用一个函数,你会等待函数执行完毕,然后拿到返回结果。 当然 ,这次并不是绝对的自上而下,编译器在保证取值正确的前提下,会进行指令重排的,但是当涉及取值时,会保证自上而下时的顺序。

而异步,则是说代码的执行,特别是函数 的执行,并不是按照你书写时的顺序 执行的。比如消息发布,虽然a先发布消息,b后发布了消息,但是仍然 可能b的消息先被收到。这就是异步。或者说两个函数分别被两个线程执行,就能并行。这也是异步。 最明显的就是函数调用,如果函数执行是异步的,你会立即 返回,拿不到执行结果,而函数的执行结果会在另外的不确定的时间通知给你。 多线程或者多进程,或者叫做并发 这是实现异步的一个方式。但是多线程并不一定就能实现异步,比如有太多的共享资源时,就需要做同步锁等待,其实这是在同步,你的效率并未得到提高。要想充分并发,必须 先做到异步,然后才能最大限度 的利用并发来提高性能。

Thinking in RxJava

Architect with MVVM

软件架构方式从MVC到MVP,再到MVVM,其实是并无本质上的区别,都是为了能把数据,业务逻辑和UI区分开来,进行解耦。而MVVM强调UI要响应数据进行自动更新,与Reactive的核心思想是一致的,因此Reactive界更习惯使用MVVM来作为架构方式。 因为RxJava是Reactive的模式,也就是说它的核心思想是Reactive,是push based数据流方式。 因此,比较适合MVVM方式,因为ViewModel的存在就是为了接收数据,然后它负责主动去刷新View。 具体架构原则与方式还需要进一步总结。

设计原则

不可变性Immutable object

数据要是纯数据类型,且是Immutable的,简单言之,数据对象所有的域都应该是final的,对象提供的方法只有getters,以及构造方法。一定不能让对象有改变自身状态的方法,这是为了保持immutability,管道计算过程中,当有状态发生变化时,需要创建一个新的对象,基于原对象,做些状态变化,然后生成一个新的对象。

存储时,只需要存储原始数据即可,中间使用的数据和状态,也即是可以通过从原始数据 计算得到的数据和状态,不需要存储,这实际上就是搭建的管道的目的啊。

函数要无副作用和幂等

函数与方法,要是纯函数,也就是说接受一些参数输入,然后产生一些输出,不能有副作用,不能对函数定义范围外的状态和变量产生依赖。而且要幂等,也就说给定同一个参数,多次调用,得到的结果都是一样的。

一个Observable实例只能被subscribe一次,一旦被subscribe,就代表着管道到达了终点,数据到此结束不会继续流动了。当subscribe了后,即使你再把这个Observable接到另外的Observable上面去,它也不会再向后面的管道(Observable)发射数据。这个需要特别注意,subscribe一定是要在最后做的事情。 如果需要subscribe两次,说明你需要不同的数据,要不然不合逻辑,如果是同数据类型,你只需要在一个subscibe做多件事情就可以了(比如刷新两个View),即使是需要不同的数据,那么就需要搭建管道进行计算,而一旦通过了operator,就会产生一个新的Observable实例(这也是为啥能连用很多点的原因,它每个operator都返回一个新的实例),因为是新的实例,所以也就可以再次subscribe。这实际上是相当于给原管道接出分支,源头数据会通过分支进行流动。

Immutable数据加上纯函数,一起就可以保证线程安全,你在operator过程中切换线程是很安全的。但如果你在函数中有依赖其他全局变量,那么结果将会是灾难性的。

依赖的原则是,ViewModel只知道Model,Model只知道Store,注意反过来不行(Store不知道Model,Model也不知道ViewModel)。它们的输出都是Observable,因此从上到下是直接依赖,通过提供的方法或者operator,而反向的反馈则是通过Observable本身。具体的,ViewModel调用Model的方法,或者直接通过operator来使用Model,反向的反馈则是通过Model给出的Observable,Model不能直接返回基本的数据对象;同理Model与Store之间也是如此。

ViewModel以及,Model和Store都要纯粹一些,不能有平台的依赖,目的就是为了方便测试。平台的依赖,要从外部传入。Activity或者Service,这些重要的组件,干的就是Container和组织者的身份,它创建ViewModel,Model以及Store所需要的输入,然后创建这些对象,并把它们拼装在一起,管理它们的生命周期。至于平台依赖,这些东西与Reactive也并不冲突啊,把它们封装好了后,接入Store即可了。

一些简单的逻辑可能直接在Container中写了也是可以的,没必要非要传入ViewModel。

推荐书籍

《RxJava for Android Developers》

这本书的侧重点在于Reactive,而非RxJava,它有大量的项目实例,来展示如何用Reactive的思想构建和架构一个项目。它关于RxJava本身介绍的不多,远不及文档详细,但它的重点在于项目,如何用纯Reactive的方式来架构一个项目,并且项目都是真实可运行的。书中的示例,以章节为单位,每一章都是一个完整的项目,所以它也不光涉及RxJava,也会包含一些其他的,如网络库等等。

对于如何把握RxJava的核心精髓,以及如何以Reactive的方式来构建一个项目,这本书是相当不错的参考。

这本书读起来也是相当的费劲,有二方面原因,一是它毕竟都是活生生的项目,而项目必然会涉及除RxJava以外的东西,如项目本身的业务逻辑,以及像网络库等等,这些东西与书的主题并不直接相关,都没有详细的讲解,这就非常影响对章节的整体的理解程度;另外一个原因,就是书中的前后流畅度不好,每一章节都是一步步的向你展示 如何用Reactive方式从零构建 一个项目,也就是说项目代码有迭代,但是它总是前后对应不上,比如说文字部分说某某个方法或者函数,与书中给出的代码片断对应不上,而书中的代码片断全连在一起,也不是完整的,且与代码示例包中的代码也对应不上,代码是有迭代的,代码示例包中肯定是最终的代码,但是书中的文字以及书中的代码片断都是迭代过程中的。这就导致读起来相当的费劲,前后对应不上,有时候不得不直接把源码翻出来看,但它与书中的描述也对应不上。

从这里,也可以看出编程书籍的无奈,特别是以完整项目为示例的书籍,因为项目必然会有迭代的过程,小步迭代,每一步都能run是比较好的迭代方式,而且项目当中必然会有大量的编程工具生成的一些冗余代码。那么,摆在作者面前就是一个难题,如何把代码与文字更好的结合在一起。很多差劲的作者会把项目完整代码全贴在书中,这是相当差劲的作法,虽然说足够完整,但是代码会占用大量的篇幅,项目中的有大量的代码也是编程工具生成的冗余 代码,更会占用大量的篇幅,这纯是凑字数的做法。另外的做法,就是像这本书的作者这样,书中仅贴出一些关键的代码片断,完整的代码要去找书的示例源码包。前提是读者要能非常容易的获得到源码包。

但是,为了更好的理解,因为读者读书的时候,可能不能方便的查看示例源码包,所以 书中的章节要与关键代码片断要做好流畅性,前后要能对应得起来。然后示例源码包中,最好分成几批,以展示项目的迭代过程。

这本书,终于读完了,还是比较费劲的,花了远超当时预估 的时间,但仍不够,对于Reactive的思想把握仍不够。书中的示例确实很好,值得继续重构和优化,以作为实践。

《Functional Reactive Programming》

这是第一本详细论述FRP编程范式的书,值得详细研读,而且非常棒的是这本书有在线版本的,可以直接在线阅读

参考资料

Comments