https://www.jianshu.com/p/1765f658200a 例子写的很是好呢.
这是告别CSDN后第一次使用简书写IT类的博客,还在适应。最不适应的就是不能直接手输markdown语法标记。(好像缘由是我没有切换编辑器)java
In computing, reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. This means that it becomes possible to express static (e.g. arrays) or dynamic (e.g. event emitters) data streams with ease via the employed programming language(s), and that an inferred dependency within the associated execution model exists, which facilitates the automatic propagation of the change involved with data flow.react
-- Wikipediaexpress
以上解释来自维基百科,在计算机领域,响应式编程是一个专一于数据流和变化传递的异步编程范式。这意味着可使用编程语言很容易地表示静态(例如数组)或动态(例如事件发射器)数据流,而且在关联的执行模型中,存在着可推断的依赖关系,这个关系的存在有利于自动传播与数据流有关的更改。编程
抛开大段大段的概念,咱们先搞清楚一件事情:什么是编程范式?数组
通俗的说:编程是为了解决问题,而解决问题能够有多种视角和思路,其中具备普适性的模式被归结为范式。咱们常说的:“面向对象”,“面向过程”都是编程范式。markdown
响应式编程是一种从数据流和变化出发的解决问题的模式。因此要研究响应式编程,必定要牢记已经掌握的OO(面向对象,笔者妄断你们OO的思想都是很根深蒂固了)来作对比,也必定要抛开OO避免钻牛角尖。框架
在展开这个问题前,咱们先看一个故事,引自知乎:小故事异步
摘抄以下:async
老张爱喝茶,废话不说,煮开水。编程语言
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张以为本身有点傻2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张仍是以为本身有点傻,因而变高端了,买了把会响笛的那种水壶。水开以后,能大声发出嘀~~~~的噪音。3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张以为这样傻等意义不大4 老张把响水壶放到火上,去客厅看电视,水壶响以前再也不去看它了,响了再去拿壶。(异步非阻塞)
老张以为本身聪明了。所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。虽然都能干活,但响水壶能够在本身完工以后,提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询本身(状况2中),形成老张效率的低下。
所谓阻塞非阻塞,仅仅对于老张而言。立等的老张,阻塞;看电视的老张,非阻塞。状况1和状况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。因此通常异步是配合非阻塞使用的,这样才能发挥异步的效用。
上面这个小故事仍是有点问题,但基本能够说明问题了。
响应,必定是对一个事件、一个信号(诸如此类的描述)产生了反应。响水壶的响应是什么呢?水温达到必定程度,水壶的反应是会响。水壶响了,声音传递给老张,老张的反应是去关水壶。
再看普通水壶,水温达到必定程度,水壶没有反应,水的反应是冒气泡,冒水雾。只是这个信号不太容易传递,要跑过来看,因此老张只能以轮训的方式来办事情,无法跑到一边等通知。
对于两个水壶而言,烧水都是阻塞的,水没烧完就干不了其余的事情(好比说拿来砸胡桃???)
ok,回到咱们的问题:为何是异步?
回归到本质回答这个问题:响应式编程,本质上是对数据流或某种变化所做出的反应,可是这个变化何时发生是未知的,因此他是一种基于异步、回调的方式在处理问题。
正如副标题,在网上搜索到的绝大多数的博客都会说着说着就在教你如何使用RxAndroid。各位,请记住如下几点:
RxAndroid(或RxJava)是很优秀的响应式编程框架。
你并不是必定须要使用RxAndroid。
RxAndroid并不像那些博客里面说的那样会让你的代码变得更可读。
这里我直接进入第三点。取用扔物线推荐RxJava中的例子:以下这段代码:
Observable.from(folders) .flatMap((Func1) (folder) -> { Observable.from(file.listFiles()) }) .filter((Func1) (file) -> { file.getName().endsWith(".png") }) .map((Func1) (file) -> { getBitmapFromFile(file) }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe((Action1) (bitmap) -> { imageCollectorView.addImage(bitmap) });
就这段代码,是否须要从上到下仔细阅读一遍以后才能才会知道他的意图?
甚至,为了精读代码,他多是这样:
Observable.from(folders) .flatMap(new Func1<File, Observable<File>>() { @Override public Observable<File> call(File file) { return Observable.from(file.listFiles()); } }) .filter(new Func1<File, Boolean>() { @Override public Boolean call(File file) { return file.getName().endsWith(".png"); } }) .map(new Func1<File, Bitmap>() { @Override public Bitmap call(File file) { return getBitmapFromFile(file); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Bitmap>() { @Override public void call(Bitmap bitmap) { imageCollectorView.addImage(bitmap); } });
ok,请容许我再问一个问题,如此简介的代码,您打算单独用一个类来放吗?
若是对于任何一个处理相似业务逻辑的rx代码段都使用类来放,可能类数量会爆炸,并且这些类的命名看起来会很奇葩。若不这样,您的业务实现类中将充斥诸如此类不精读不敢肯定语义、容易被误修改、不容易测试的代码。面对这样的代码的时候只会是如履薄冰战战兢兢。
No,我只是反对滥用Rx,我同意对某些高度抽象的异步行为使用Rx构建具备语义性的框架代码,例如:编写MVVM分层框架。反对对任何业务细节都去作“一切皆流”的无脑工做。毕竟:业务是须要逐渐迭代发展的,对于有测试代码支撑的、同时有较强语义性的类,咱们泛读代码就能够“闻弦歌而知雅意”,对于须要重构何处代码,修改何处逻辑心中有数,而没必要将“流”再反转回“实际的相互关系”,再打乱,修改,再组织成流,再恶心下一次迭代,并且,最关键的是“你可能要从不少的流中找出这一个流”。