- 浏览: 2204192 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (1240)
- mac/IOS (287)
- flutter (1)
- J2EE (115)
- android基础知识 (582)
- android中级知识 (55)
- android组件(Widget)开发 (18)
- android 错误 (21)
- javascript (18)
- linux (70)
- 树莓派 (18)
- gwt/gxt (1)
- 工具(IDE)/包(jar) (18)
- web前端 (17)
- java 算法 (8)
- 其它 (5)
- chrome (7)
- 数据库 (8)
- 经济/金融 (0)
- english (2)
- HTML5 (7)
- 网络安全 (14)
- 设计欣赏/设计窗 (8)
- 汇编/C (8)
- 工具类 (4)
- 游戏 (5)
- 开发频道 (5)
- Android OpenGL (1)
- 科学 (4)
- 运维 (0)
- 好东西 (6)
- 美食 (1)
最新评论
-
liangzai_cool:
请教一下,文中,shell、C、Python三种方式控制led ...
树莓派 - MAX7219 -
jiazimo:
...
Kafka源码分析-序列5 -Producer -RecordAccumulator队列分析 -
hp321:
Windows该命令是不是需要安装什么软件才可以?我试过不行( ...
ImageIO读jpg的时候出现javax.imageio.IIOException: Unsupported Image Type -
hp321:
Chenzh_758 写道其实直接用一下代码就可以解决了:JP ...
ImageIO读jpg的时候出现javax.imageio.IIOException: Unsupported Image Type -
huanghonhpeng:
大哥你真强什么都会,研究研究。。。。小弟在这里学到了很多知识。 ...
android 浏览器
简介
说起 RxJava ,相信诸多 Android 开发者都不会陌生。作为一个知名的响应式编程库,从前年开始逐渐变得火热,从小众到被众多 Android 开发者们广泛引入与流传,其在 GitHub 的仓库截止笔者写这篇文章时,已经有16400+个 star 。甚至有一些大牛专门为 Android 写了 RxJava 的适配库,如
为什么 RxJava 如此受到 Android 开发者们的欢迎。我想不外乎两个原因。
1. 异步
2. 链式操作
异步
对 Android 线程有所了解的朋友都知道, Android的 UI 绘制 与 事件响应是在主线程的,为了保证界面的流畅性,很多耗时操作如读写数据库、读写文件、请求网络,我们都会挪到异步线程去完成,再回调到主线程。当然在4.0以后主线程直接就不允许请求网络了。
在过去没有 RxJava 的时候,开发者一般都是通过 AsyncTask , Thread ,更好些的就是通过线程池来完成这些任务。而有了 RxJava 以后,简简单单的一句话就可以随意的切换线程,简直不用太舒服。
最典型的 RxJava 中的Observable类,提供了2个函数, 分别是subscribeOn与observeOn。前者可以切换被观察时的线程(如果说数据发射的线程不够严谨,数据并非一定在观察时发射的,尤其是开发者自定义OnSubscribe时),后者可以切换数据被消费时的线程。
举一个切换线程的例子:
这里我们没有任何数据,就仅仅发射了一个onComplete,但是在切换线程的代码中,我们增加了onComplte时要额外执行的代码,输出结果如下:
08-27 10:47:41.173 6741-6741/com.dieyidezui.rxjavademo I/debug: main
08-27 10:47:41.201 6741-6762/com.dieyidezui.rxjavademo I/debug: RxIoScheduler-2
08-27 10:47:41.217 6741-6741/com.dieyidezui.rxjavademo I/debug: main
这仅仅是简单的例子, RxJava 提供了很多便捷的操作符供我们使用,如map、filter、flatMap、merge、concat等。可见当熟练使用后对我们的编程效率确实有很大帮助。尤其是 MVP 模式, RxJava 与之结合可谓是”天作之合”。
链式操作
上面笔者演示的代码其实就是 RxJava 的典型使用方式:
其中中间操作包含诸多用法, 如果切换线程,变换数据等。
为什么我说链式操作很好。第一,链式逻辑替代深度回调逻辑,容易编写,不易出 BUG 。第二,RxJava 提供诸多了整体处理数据的操作符,非常实用。第三,配合 Java8 的 lambda 表达式,使代码简短优雅。
好了,对 RxJava 的介绍就此为止了。进阶用法、原理剖析以后会有专门的文章。对 RxJava 不熟悉的同学,建议先去看一下官方的 wiki 。链接: https://github.com/ReactiveX/RxJava/wiki
RxJava2.0
前天, RxJava终于发布了2.0 RC1 版本,一直关注于此的笔者立刻就进去尝鲜了。结合官方的介绍,笔者总结并翻译了一些与 1.x 的异同与大家分享。
包名与MAVEN依赖
首先要说的就是 RxJava 2和1是互相独立的。因此包名与 maven 的依赖也是不一样的,就类似于 OkHttp 3与2一样。
RxJava 2.x的依赖是全新的io.reactivex.rxjava2:rxjava:2.x.y,并且类处于该io.reactivex包名下,而不再是rx。
接口变化
RxJava2 是遵循 Reactive Streams Specification 的规范完成的,新的特性依赖其提供的4个基础接口。分别是
Flowable与Observable
新的实现叫做Flowable, 同时旧的Observable也保留了。因为在 RxJava1.x 中,有很多事件不被能正确的背压,从而抛出MissingBackpressureException。
举个简单的例子,在 RxJava1.x 中的 observeOn, 因为是切换了消费者的线程,因此内部实现用队列存储事件。在 Android 中默认的 buffersize 大小是16,因此当消费比生产慢时, 队列中的数目积累到超过16个,就会抛出MissingBackpressureException, 初学者很难明白为什么会这样,使得学习曲线异常得陡峭。
而在 2.0 中,Observable 不再支持背压,而Flowable 支持非阻塞式的背压。并且规范要求,所有的操作符强制支持背压。幸运的是, Flowable 中的操作符大多与旧有的 Observable 类似。
Single、Completable
Single 与 Completable 都基于新的 Reactive Streams 的思想重新设计了接口,主要是消费者的接口, 现在他们是这样的:
Subscriber
对比一下 Subscriber :
我们会发现和以前不一样的是多了一个onSubscribe的方法,Subscription如下:
Subscription
熟悉 RxJava 1.x 的朋友能发现, 新的Subscription更像是综合了旧的Producer与Subscription的综合体。他既可以向上游请求数据,又可以打断并释放资源。而旧的Subscription在这里因为名字被占,而被重新命名成了Disposable
Disposable
这里最大的不同就是这个onSubscribe,根据 Specification, 这个函数一定是第一个被调用的, 然后就会传给调用方一个Subscription,通过这种方式组织新的背压关系。当我们消费数据时,可以通过Subscription对象,自己决定请求数据。
这里就可以解释上面的非阻塞的背压。旧的阻塞式的背压,就是根据下游的消费速度,中游可以选择阻塞住等待下游的消费,随后向上游请求数据。而新的非阻塞就不在有中间阻塞的过程,由下游自己决定取多少,还有背压策略,如抛弃最新、抛弃最旧、缓存、抛异常等。
而新的接口带来的新的调用方式与旧的也不太一样, subscribe后不再会有 Subscription 也就是如今的 Disposable,为了保持向后的兼容, Flowable 提供了 subscribeWith方法 返回当前的Subscriber对象, 并且同时提供了DefaultSubscriber, ResourceSubscriber,DisposableSubscriber,让他们提供了Disposable接口, 可以完成和以前类似的代码:
收回 create 方法权限
在RxJava 1.x 最明显的问题就是由于 create 的太过开放,导致其被开发者滥用,而不是学习使用提供的操作符。
并且用户对 RxJava 不够了解,导致各种各样的问题,如背压、异常处理等。
由于规范要求所有的操作符强制支持背压,因此新的 create 采用了保守的设计,让用户实现FlowableOnSubscribe接口,并选取背压策略,然后在内部实现封装支持背压,简单的例子如下:
Functions可以抛出异常
新的ActionX、FunctionX的方法声明都增加了一个throws Exception,这带来了显而易见的好处,现在我们可以这样写:
Flowable.just("file.txt")
.map(name -> Files.readLines(name))
.subscribe(lines -> System.out.println(lines.size()), Throwable::printStackTrace);
而在以前是不行的, 因为Files.readLines(name)会显式的抛出一个IOException。这样对 lambda 更加友好,而不必再去 try catch 。
Scheduler可以直接schedule
在以前是必须要先createWorker,用 Worker 对象去 shedule, 现在可以直接在Scheduler用这些方法:
这算是一个小优化,方便开发者使用。
Observable的一些继承并入了Flowable中
如ConnectableObservable、BlockObservable等,这样可以直接在Flowable中写出这样的代码:
其他修改
还有一些普通开发者不太在意的修改:
等其他变动。
结语
RxJava 作为开源的经典之作,笔者一直都有所关注。后续笔者会继续为大家带来 RxJava 的源码解析与进阶使用系列等。感谢大家的阅读,如有不知之处,欢迎讨论交流。
参考文献
Reactive Streams specification
官方wiki
说起 RxJava ,相信诸多 Android 开发者都不会陌生。作为一个知名的响应式编程库,从前年开始逐渐变得火热,从小众到被众多 Android 开发者们广泛引入与流传,其在 GitHub 的仓库截止笔者写这篇文章时,已经有16400+个 star 。甚至有一些大牛专门为 Android 写了 RxJava 的适配库,如
- RxAndroid
- RxBinding
- RxLifecycle
为什么 RxJava 如此受到 Android 开发者们的欢迎。我想不外乎两个原因。
1. 异步
2. 链式操作
异步
对 Android 线程有所了解的朋友都知道, Android的 UI 绘制 与 事件响应是在主线程的,为了保证界面的流畅性,很多耗时操作如读写数据库、读写文件、请求网络,我们都会挪到异步线程去完成,再回调到主线程。当然在4.0以后主线程直接就不允许请求网络了。
在过去没有 RxJava 的时候,开发者一般都是通过 AsyncTask , Thread ,更好些的就是通过线程池来完成这些任务。而有了 RxJava 以后,简简单单的一句话就可以随意的切换线程,简直不用太舒服。
最典型的 RxJava 中的Observable类,提供了2个函数, 分别是subscribeOn与observeOn。前者可以切换被观察时的线程(如果说数据发射的线程不够严谨,数据并非一定在观察时发射的,尤其是开发者自定义OnSubscribe时),后者可以切换数据被消费时的线程。
举一个切换线程的例子:
Log.i("debug", Thread.currentThread().getName()); Observable.empty() .doOnCompleted(new Action0() { @Override public void call() { Log.i("debug", Thread.currentThread().getName()); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnCompleted(new Action0() { @Override public void call() { Log.i("debug", Thread.currentThread().getName()); } }) .subscribe();
这里我们没有任何数据,就仅仅发射了一个onComplete,但是在切换线程的代码中,我们增加了onComplte时要额外执行的代码,输出结果如下:
引用
08-27 10:47:41.173 6741-6741/com.dieyidezui.rxjavademo I/debug: main
08-27 10:47:41.201 6741-6762/com.dieyidezui.rxjavademo I/debug: RxIoScheduler-2
08-27 10:47:41.217 6741-6741/com.dieyidezui.rxjavademo I/debug: main
这仅仅是简单的例子, RxJava 提供了很多便捷的操作符供我们使用,如map、filter、flatMap、merge、concat等。可见当熟练使用后对我们的编程效率确实有很大帮助。尤其是 MVP 模式, RxJava 与之结合可谓是”天作之合”。
链式操作
上面笔者演示的代码其实就是 RxJava 的典型使用方式:
- 发射数据源
- 中间操作
- 处理结果
其中中间操作包含诸多用法, 如果切换线程,变换数据等。
为什么我说链式操作很好。第一,链式逻辑替代深度回调逻辑,容易编写,不易出 BUG 。第二,RxJava 提供诸多了整体处理数据的操作符,非常实用。第三,配合 Java8 的 lambda 表达式,使代码简短优雅。
好了,对 RxJava 的介绍就此为止了。进阶用法、原理剖析以后会有专门的文章。对 RxJava 不熟悉的同学,建议先去看一下官方的 wiki 。链接: https://github.com/ReactiveX/RxJava/wiki
RxJava2.0
前天, RxJava终于发布了2.0 RC1 版本,一直关注于此的笔者立刻就进去尝鲜了。结合官方的介绍,笔者总结并翻译了一些与 1.x 的异同与大家分享。
包名与MAVEN依赖
首先要说的就是 RxJava 2和1是互相独立的。因此包名与 maven 的依赖也是不一样的,就类似于 OkHttp 3与2一样。
RxJava 2.x的依赖是全新的io.reactivex.rxjava2:rxjava:2.x.y,并且类处于该io.reactivex包名下,而不再是rx。
接口变化
RxJava2 是遵循 Reactive Streams Specification 的规范完成的,新的特性依赖其提供的4个基础接口。分别是
- Publisher
- Subscriber
- Subscription
- Processor
Flowable与Observable
新的实现叫做Flowable, 同时旧的Observable也保留了。因为在 RxJava1.x 中,有很多事件不被能正确的背压,从而抛出MissingBackpressureException。
举个简单的例子,在 RxJava1.x 中的 observeOn, 因为是切换了消费者的线程,因此内部实现用队列存储事件。在 Android 中默认的 buffersize 大小是16,因此当消费比生产慢时, 队列中的数目积累到超过16个,就会抛出MissingBackpressureException, 初学者很难明白为什么会这样,使得学习曲线异常得陡峭。
而在 2.0 中,Observable 不再支持背压,而Flowable 支持非阻塞式的背压。并且规范要求,所有的操作符强制支持背压。幸运的是, Flowable 中的操作符大多与旧有的 Observable 类似。
Single、Completable
Single 与 Completable 都基于新的 Reactive Streams 的思想重新设计了接口,主要是消费者的接口, 现在他们是这样的:
interface SingleObserver<T> { void onSubscribe(Disposable d); void onSuccess(T value); void onError(Throwable error); } interface CompletableObserver<T> { void onSubscribe(Disposable d); void onComplete(); void onError(Throwable error); }
Subscriber
对比一下 Subscriber :
public interface Subscriber<T> { public void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); }
我们会发现和以前不一样的是多了一个onSubscribe的方法,Subscription如下:
Subscription
public interface Subscription { public void request(long n); public void cancel(); }
熟悉 RxJava 1.x 的朋友能发现, 新的Subscription更像是综合了旧的Producer与Subscription的综合体。他既可以向上游请求数据,又可以打断并释放资源。而旧的Subscription在这里因为名字被占,而被重新命名成了Disposable
Disposable
public interface Disposable { void dispose(); boolean isDisposed(); }
这里最大的不同就是这个onSubscribe,根据 Specification, 这个函数一定是第一个被调用的, 然后就会传给调用方一个Subscription,通过这种方式组织新的背压关系。当我们消费数据时,可以通过Subscription对象,自己决定请求数据。
这里就可以解释上面的非阻塞的背压。旧的阻塞式的背压,就是根据下游的消费速度,中游可以选择阻塞住等待下游的消费,随后向上游请求数据。而新的非阻塞就不在有中间阻塞的过程,由下游自己决定取多少,还有背压策略,如抛弃最新、抛弃最旧、缓存、抛异常等。
而新的接口带来的新的调用方式与旧的也不太一样, subscribe后不再会有 Subscription 也就是如今的 Disposable,为了保持向后的兼容, Flowable 提供了 subscribeWith方法 返回当前的Subscriber对象, 并且同时提供了DefaultSubscriber, ResourceSubscriber,DisposableSubscriber,让他们提供了Disposable接口, 可以完成和以前类似的代码:
ResourceSubscriber<Integer> subscriber = new ResourceSubscriber<Integer>() { @Override public void onStart() { request(Long.MAX_VALUE); } @Override public void onNext(Integer t) { System.out.println(t); } @Override public void onError(Throwable t) { t.printStackTrace(); } @Override public void onComplete() { System.out.println("Done"); } }; Flowable.range(1, 10).delay(1, TimeUnit.SECONDS).subscribe(subscriber); subscriber.dispose();
收回 create 方法权限
在RxJava 1.x 最明显的问题就是由于 create 的太过开放,导致其被开发者滥用,而不是学习使用提供的操作符。
并且用户对 RxJava 不够了解,导致各种各样的问题,如背压、异常处理等。
由于规范要求所有的操作符强制支持背压,因此新的 create 采用了保守的设计,让用户实现FlowableOnSubscribe接口,并选取背压策略,然后在内部实现封装支持背压,简单的例子如下:
Flowable.create((FlowableEmitter<Integer> emitter) -> { emitter.onNext(1); emitter.onNext(2); emitter.onComplete(); }, BackpressureStrategy.BUFFER);
Functions可以抛出异常
新的ActionX、FunctionX的方法声明都增加了一个throws Exception,这带来了显而易见的好处,现在我们可以这样写:
Flowable.just("file.txt")
.map(name -> Files.readLines(name))
.subscribe(lines -> System.out.println(lines.size()), Throwable::printStackTrace);
而在以前是不行的, 因为Files.readLines(name)会显式的抛出一个IOException。这样对 lambda 更加友好,而不必再去 try catch 。
Scheduler可以直接schedule
在以前是必须要先createWorker,用 Worker 对象去 shedule, 现在可以直接在Scheduler用这些方法:
public abstract class Scheduler { public Disposable scheduleDirect(Runnable task) { ... } public Disposable scheduleDirect(Runnable task, long delay, TimeUnit unit) { ... } public Disposable scheduleDirectPeriodically(Runnable task, long initialDelay, long period, TimeUnit unit) { ... } public long now(TimeUnit unit) { ... } // ... rest is the same: lifecycle methods, worker creation }
这算是一个小优化,方便开发者使用。
Observable的一些继承并入了Flowable中
如ConnectableObservable、BlockObservable等,这样可以直接在Flowable中写出这样的代码:
List<Integer> list = Flowable.range(1, 100).toList().blockingFirst();
其他修改
还有一些普通开发者不太在意的修改:
- hook方式变化,现在可以通过提供接口在 runtime hook
- 部分在 1.x 中 被标记@Beta、@Experimental的操作符现在合并到正式版里了
- 由于类结构的变动,一些类名的变化
等其他变动。
结语
RxJava 作为开源的经典之作,笔者一直都有所关注。后续笔者会继续为大家带来 RxJava 的源码解析与进阶使用系列等。感谢大家的阅读,如有不知之处,欢迎讨论交流。
参考文献
Reactive Streams specification
官方wiki
发表评论
-
带你深入理解 FLUTTER 中的字体“冷”知识
2020-08-10 23:40 635本篇将带你深入理解 Flutter 开发过程中关于字体和文 ... -
Flutter -自定义日历组件
2020-03-01 17:56 1111颜色文件和屏幕适配的文件 可以自己给定 import ... -
Dart高级(一)——泛型与Json To Bean
2020-02-23 19:13 1005从 Flutter 发布到现在, 越来越多人开始尝试使用 Da ... -
flutter loading、Progress进度条
2020-02-21 17:03 1181Flutter Progress 1 条形无固定值进度条 ... -
Flutter使用Https加载图片
2020-02-21 01:39 1020Flutter使用Https加载图片 使用http加载图片出 ... -
flutter shared_preferences 异步变同步
2020-02-21 00:55 848前言 引用 在开发原生iOS或Native应用时,一般有判断上 ... -
Flutter TextField边框颜色
2020-02-19 21:31 937监听要销毁 myController.dispose(); T ... -
flutter Future的正确用法
2020-02-18 21:55 808在flutter中经常会用到异步任务,dart中异步任务异步处 ... -
记一次Flutter简单粗暴处理HTTPS证书检验方法
2020-02-18 14:13 979最近在做Flutter项目到了遇到一个无解的事情,当使用Ima ... -
flutter 获取屏幕宽度高度 通知栏高度等屏幕信息
2019-07-27 08:39 1344##MediaQuery MediaQuery.of(con ... -
关于flutter RefreshIndicator扩展listview下拉刷新的问题
2019-07-10 19:40 1143当条目过少时listview某些嵌套情况下可能不会滚动(条目 ... -
flutter listview 改变状态的时候一直无限添加
2019-07-10 16:01 791setstate的时候会一直无限的调用listview.bui ... -
Flutter Android端启动白屏问题的解决
2019-07-09 00:51 1525问题描述 Flutter 应用在 Android 端上启动时 ... -
Flutter中SnackBar使用
2019-07-08 23:43 781底部弹出,然后在指定时间后消失。 注意: build(Bui ... -
Flutter 之点击空白区域收起键盘
2019-07-08 18:43 1792点击空白处取消TextField焦点这个需求是非常简单的,在学 ... -
Flutter 弹窗 Dialog ,AlertDialog,IOS风格
2019-07-08 18:04 1383import 'package:flutter/mate ... -
flutter ---TextField 之 输入类型、长度限制
2019-07-08 14:30 2337TextField想要实现输入类型、长度限制需要先引入impo ... -
【flutter 溢出BUG】键盘上显示bottom overflowed by 104 PIXELS
2019-07-08 11:13 1567一开始直接使用Scaffold布局,body:new Colu ... -
解决Flutter项目卡在Initializing gradle...界面的问题
2019-07-07 12:53 880Flutter最近很火,我抽出了一点时间对Flutter进行了 ... -
关于android O 上 NotificationChannel 的一些注意事项
2019-07-04 11:47 941最近在适配android O,遇到个问题,应用中原本有设置界面 ...
相关推荐
RAID 2.0 技术的特性包括: 1. 大规模硬盘组:由几个、几十个甚至上百个硬盘组成。 2. 分块化:硬盘被划分为几十兆至几百兆的分块。 3. 分块组内的RAID计算:没有独立的热备盘,而是使用分块组内的预留热备空间。 4....
RAID 2.0 和 RAID 2.0+ 是两种先进的存储技术,它们旨在解决传统RAID在处理大容量硬盘时面临的重构时间过长和数据安全性问题。这两种技术由包括华为和3PAR在内的创新公司开发,旨在适应现代数据中心的需求,特别是在...
浅谈RxJava+Retrofit+OkHttp 封装使用 RxJava 是一个基于 Reactive Extensions 库的 Java 版本,它提供了一个强大的编程模型,可以简化异步编程,使得开发者能够更方便地处理异步数据。RxJava 通过 Observable 和 ...
深入浅出财务管理2.0
Vue 2.0 响应式是指 Vue 框架中实现数据双向绑定的机制,实现了视图与数据的自动同步。下面是 Vue 2.0 响应式的基本思路: 一、数据劫持 在 Vue 2.0 中,我们使用 Object.defineProperty 来实现数据劫持,将数据...
运行时异常通常与编程错误相关,编译器不会强制捕获;而检查性异常是必须处理的,否则编译无法通过。 在处理业务异常时,一种常见的策略是重试。例如,在网络请求中,如果因为网络不稳定导致请求失败,可能只需要...
浅议等保2.0下的高校网络安全防护体系.docx
通信原理基础知识讲解,电子科大教材课件,挺不错的
)深入浅出RxJava(三--响应式的好处)深入浅出RxJava(四-在Android中使用响应式编程)如何升级到RxAndroid1.0 -适合使用Rx 0.x版本的用户升级的时候参考可能是东半球最全的 RxJava 使用场景小结RxJava系列1(简介)...
Spring Boot 2.0 是一个重大更新,引入了许多变化,旨在提高性能、稳定性和易用性。对于那些正在考虑将现有的Spring Boot 1.x 应用程序迁移到2.0 版本的开发者来说,理解这些变化至关重要。以下是一些主要的迁移注意...
浅谈能源信息安全与风险控制【最新版】.docx浅谈能源信息安全与风险控制【最新版】.docx浅谈能源信息安全与风险控制【最新版】.docx浅谈能源信息安全与风险控制【最新版】.docx浅谈能源信息安全与风险控制【最新版】...
教育信息化2.0时代标志着我国教育领域的一次重大变革,这一时期强调的是信息技术与教育教学的深度融合,以提升教育质量和效率。在这个背景下,语文教师的信息素养成为教育改革的关键因素。信息素养不仅包括教师对...
《豪越HYDO 等保2.0解读与运维管理软件浅谈(一)》 等级保护2.0(等保2.0)是中国网络安全等级保护制度的最新标准,旨在提升各行业的信息安全保障能力。它从管理和技术两个层面提出了全面的安全保护要求,对网络安全...
在Visual Studio中,你可以创建一个ASP.NET Core 2.0的空项目。在`Startup.cs`文件中,你会看到`Configure`方法。这个方法中,`IApplicationBuilder`对象提供了`Run`和`Use`这两个扩展方法来添加中间件到请求处理...