java 2>>2_RxJava2轻松入门

2023-05-16

Demo地址

本Demo旨在帮助从未接触过RxJava的同学直接入坑RxJava2,如丝般顺滑,万水千山总是情,留个star行不行?

RxJava & RxAndroid (2.0版)#

定义

RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.

一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库

初学者如果看到这个准确但晦涩的定义肯定一脸懵逼,不过我们我们只要把握重点即可:

异步

基于事件

观察者模式

RxAndroid - Android specific bindings for RxJava 2.This module adds the minimum classes to RxJava that make writing reactive components in Android applications easy and hassle-free.

RxAndroid在RxJava的基础上添加了最少的类使得开发Android应用中的响应式组件更加的容易和自由

特点

简洁,并不是指代码量上的那种简洁,而是逻辑上的简洁,随着程序逻辑变得越来越复杂,它依然能够保持简洁。

Github

Hello world

添加依赖

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

compile 'io.reactivex.rxjava2:rxjava:2.0.1'

简单版本

//简单版本

private void helloWorldSimple() {

//创建消费者,消费者接受一个String类型的事件

Consumer consumer = new Consumer() {

@Override

public void accept(String s) throws Exception {

Log.d(TAG, s);

}

};

//被观察者发出Hello World, 并且指定该事件的消费者为consumer

Observable.just("Hello World").subscribe(consumer);

}

运行结果

D/MainActivity: Hello World

复杂版本

private void helloWorldComplex() {

//Observer可以看做Consumer的完整版

Observer observer = new Observer() {

//当Observable调用subscribe方法时会回调该方法

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe: ");

}

//onSubscribe方法后调用

@Override

public void onNext(String value) {

Log.d(TAG, "onNext: " + value);

}

//这里没有出错,没有被调用

@Override

public void onError(Throwable e) {

Log.d(TAG, "onError: ");

}

//onNext之后调用

@Override

public void onComplete() {

Log.d(TAG, "onComplete: ");

}

};

//被观察者发出Hello World, 并且指定该事件的观察者为observer

Observable.just("Hello World").subscribe(observer);

}

运行结果

D/MainActivity: onSubscribe:

D/MainActivity: onNext: Hello World

D/MainActivity: onComplete:

变态版本

private void helloWorldPlus() {

//创建一个观察者

Observer observer = new Observer() {

//当Observable调用subscribe方法时会回调该方法

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe: ");

}

//onSubscribe方法后调用

@Override

public void onNext(String value) {

Log.d(TAG, "onNext: " + value);

}

//这里没有出错,没有被调用

@Override

public void onError(Throwable e) {

Log.d(TAG, "onError: ");

}

//onNext之后调用

@Override

public void onComplete() {

Log.d(TAG, "onComplete: ");

}

};

//创建一个Observable

Observable observable = Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter e) throws Exception {

e.onNext("Hello World");//会调用到观察者的onNext

e.onComplete();//会调用到观察者的onComplete

}

});

observable.subscribe(observer);

}

运行结果

D/MainActivity: onSubscribe:

D/MainActivity: onNext: Hello World

D/MainActivity: onComplete:

filter操作符

你早上去吃早餐,师傅是被观察者,说咱这有包子,馒头,肠粉,春卷,饺子,炒粉,你仔细想了想,发现你是最喜欢饺子的,所以把其他的都排除掉,于是你就吃到了饺子。

private void filter() {

//把Consumer可以看做精简版的Observer

Consumer consumer = new Consumer() {

//accept可以简单的看做onNext

@Override

public void accept(String s) throws Exception {

Log.d(TAG, "accept: " + s);//这里只能吃上饺子

}

};

Observable.just("包子", "馒头", "肠粉", "春卷", "饺子", "炒粉")

.filter(new Predicate() {

@Override

public boolean test(String s) throws Exception {

Log.d(TAG, "test: " + s);

return s.equals("饺子");//只允许饺子通过测试

}

})

.subscribe(consumer);

}

运行结果

D/MainActivity: test: 包子

D/MainActivity: test: 馒头

D/MainActivity: test: 肠粉

D/MainActivity: test: 春卷

D/MainActivity: test: 饺子

D/MainActivity: accept: 饺子

D/MainActivity: test: 炒粉

map操作符

map操作符能够完成数据类型的转换。 以下代码展示了一个Student到Developer的转换。

private void map() {

Observer observer = new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe: ");

}

//观察者接收到一个Developer

@Override

public void onNext(Developer value) {

Log.d(TAG, "onNext: " + value.toString());

}

@Override

public void onError(Throwable e) {

Log.d(TAG, "onError: ");

}

@Override

public void onComplete() {

Log.d(TAG, "onComplete: ");

}

};

Student student = new Student();

student.setName("Leon");

student.setAge(18);

//map操作符,从Student类型转换成Developer

Observable.just(student).map(new Function() {

@Override

public Developer apply(Student student) throws Exception {

Log.d(TAG, "apply: " + student.toString());

Developer developer = new Developer();

developer.setName(student.getName());

developer.setAge(student.getAge());

developer.setSkill("Android");

return developer;

}

}).subscribe(observer);

}

运行结果

D/MainActivity: onSubscribe:

D/MainActivity: apply: Student{name='Leon', age=18}

D/MainActivity: onNext: Developer{name='Leon', age=18, skill='Android'}

D/MainActivity: onComplete:

flatmap操作符

flatmap能够链式地完成数据类型的转换和加工。

遍历一个学校中所有班级所有学生

private void flatmapClassToStudent() {

Observable.fromIterable(new School().getClasses())

//输入是Class类型,输出是ObservableSource类型

.flatMap(new Function>() {

//输入是Class类型,输出是ObservableSource类型

@Override

public ObservableSource apply(Class aClass) throws Exception {

Log.d(TAG, "apply: " + aClass.toString());

return Observable.fromIterable(aClass.getStudents());

}

}).subscribe(

new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe: ");

}

@Override

public void onNext(Student value) {

Log.d(TAG, "onNext: " + value.toString());

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

}

});

}

运行结果

D/MainActivity: onSubscribe:

D/MainActivity: apply: Class0

D/MainActivity: onNext: Student{name='Class0_0', age=18}

D/MainActivity: onNext: Student{name='Class0_1', age=18}

D/MainActivity: onNext: Student{name='Class0_2', age=18}

D/MainActivity: apply: Class1

D/MainActivity: onNext: Student{name='Class1_0', age=18}

D/MainActivity: onNext: Student{name='Class1_1', age=18}

D/MainActivity: onNext: Student{name='Class1_2', age=18}

D/MainActivity: apply: Class2

D/MainActivity: onNext: Student{name='Class2_0', age=18}

D/MainActivity: onNext: Student{name='Class2_1', age=18}

D/MainActivity: onNext: Student{name='Class2_2', age=18}

遍历一个学校所有班级所有组的所有学生

private void flatmapClassToGroupToStudent() {

Observable.fromIterable(new School().getClasses())

//输入是Class类型,输出是ObservableSource类型

.flatMap(new Function>() {

@Override

public ObservableSource apply(Class aClass) throws Exception {

Log.d(TAG, "apply: " + aClass.toString());

return Observable.fromIterable(aClass.getGroups());

}

})

//输入类型是Group,输出类型是ObservableSource类型

.flatMap(new Function>() {

@Override

public ObservableSource apply(Group group) throws Exception {

Log.d(TAG, "apply: " + group.toString());

return Observable.fromIterable(group.getStudents());

}

})

.subscribe(

new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe: ");

}

@Override

public void onNext(Student value) {

Log.d(TAG, "onNext: " + value.toString());

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

}

});

}

运行结果

D/MainActivity: onSubscribe:

D/MainActivity: apply: Class0

D/MainActivity: apply: Group0

D/MainActivity: onNext: Student{name='Group0_0', age=18}

D/MainActivity: onNext: Student{name='Group0_1', age=18}

D/MainActivity: onNext: Student{name='Group0_2', age=18}

D/MainActivity: apply: Group1

D/MainActivity: onNext: Student{name='Group1_0', age=18}

D/MainActivity: onNext: Student{name='Group1_1', age=18}

D/MainActivity: onNext: Student{name='Group1_2', age=18}

D/MainActivity: apply: Group2

D/MainActivity: onNext: Student{name='Group2_0', age=18}

D/MainActivity: onNext: Student{name='Group2_1', age=18}

D/MainActivity: onNext: Student{name='Group2_2', age=18}

D/MainActivity: apply: Class1

D/MainActivity: apply: Group0

D/MainActivity: onNext: Student{name='Group0_0', age=18}

D/MainActivity: onNext: Student{name='Group0_1', age=18}

D/MainActivity: onNext: Student{name='Group0_2', age=18}

D/MainActivity: apply: Group1

D/MainActivity: onNext: Student{name='Group1_0', age=18}

D/MainActivity: onNext: Student{name='Group1_1', age=18}

D/MainActivity: onNext: Student{name='Group1_2', age=18}

D/MainActivity: apply: Group2

D/MainActivity: onNext: Student{name='Group2_0', age=18}

D/MainActivity: onNext: Student{name='Group2_1', age=18}

D/MainActivity: onNext: Student{name='Group2_2', age=18}

D/MainActivity: apply: Class2

D/MainActivity: apply: Group0

D/MainActivity: onNext: Student{name='Group0_0', age=18}

D/MainActivity: onNext: Student{name='Group0_1', age=18}

D/MainActivity: onNext: Student{name='Group0_2', age=18}

D/MainActivity: apply: Group1

D/MainActivity: onNext: Student{name='Group1_0', age=18}

D/MainActivity: onNext: Student{name='Group1_1', age=18}

D/MainActivity: onNext: Student{name='Group1_2', age=18}

D/MainActivity: apply: Group2

D/MainActivity: onNext: Student{name='Group2_0', age=18}

D/MainActivity: onNext: Student{name='Group2_1', age=18}

D/MainActivity: onNext: Student{name='Group2_2', age=18}

线程调度

关于RxJava的线程调度,初学者只需要掌握两个api就够够的啦。

subscribeOn

指定Observable在一个指定的线程调度器上创建。只能指定一次,如果指定多次则以第一次为准

observeOn

指定在事件传递,转换,加工和最终被观察者接受发生在哪一个线程调度器。可指定多次,每次指定完都在下一步生效。

常用线程调度器类型

Schedulers.single() 单线程调度器,线程可复用

Schedulers.newThread() 为每个任务创建新的线程

Schedulers.io() 处理io密集型任务,内部是线程池实现,可自动根据需求增长

Schedulers.computation() 处理计算任务,如事件循环和回调任务

AndroidSchedulers.mainThread() Android主线程调度器

示例

private void scheduleThreads() {

Observable.create(

new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter e) throws Exception {

Log.d(TAG, "subscribe: " + Thread.currentThread().getName());

e.onNext("Hello Leon Fan");

e.onComplete();

}

})

//指定subscribe方法在io线程池中调用

.subscribeOn(Schedulers.io())

//指定onNext方法 onComplete的方法在新建的线程中调用

.observeOn(Schedulers.newThread())

.subscribe(

new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe: " + Thread.currentThread().getName());

}

@Override

public void onNext(String value) {

Log.d(TAG, "onNext: " + Thread.currentThread().getName() + " " + value);

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

Log.d(TAG, "onComplete: " + Thread.currentThread().getName());

}

});

}

运行结果

D/MainActivity: onSubscribe: main

D/MainActivity: subscribe: RxCachedThreadScheduler-4

D/MainActivity: onNext: RxNewThreadScheduler-1 Hello Leon Fan

D/MainActivity: onComplete: RxNewThreadScheduler-1

如果将示例中的.observeOn(Schedulers.newThread())改成AndroidSchedulers.mainThread(),则运行结果如下:

D/MainActivity: onSubscribe: main

D/MainActivity: subscribe: RxCachedThreadScheduler-5

D/MainActivity: onNext: main Hello Leon Fan

D/MainActivity: onComplete: main

RxJava与Retrofit集成

我们做一个Demo通过网络请求获取豆瓣电影Top10的列表来展示RxJava和Retrofit的集成的姿势。

5b32af1edced

movielistactivity.png

Retrofit集成

添加依赖

compile 'com.squareup.retrofit2:retrofit:2.1.0'

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

//compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' 官方adapter仅支持rxjava1.0

compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

创建网络接口

public interface Api {

@GET("top250")

Observable listTop250(@Query("start") int start, @Query("count") int count);

}

实现Api

public class MovieRetrofit {

private static MovieRetrofit sMovieRetrofit;

private final Api mApi;

public static MovieRetrofit getInstance() {

if (sMovieRetrofit == null) {

synchronized (MovieRetrofit.class) {

if (sMovieRetrofit == null) {

sMovieRetrofit = new MovieRetrofit();

}

}

}

return sMovieRetrofit;

}

private MovieRetrofit() {

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.douban.com/v2/movie/")

.addConverterFactory(GsonConverterFactory.create())

.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

.build();

mApi = retrofit.create(Api.class);

}

public Api getApi() {

return mApi;

}

}

发送网络请求刷新列表

Observable movieBeanObservable = MovieRetrofit.getInstance().getApi().listTop250(0, 10);

movieBeanObservable.subscribeOn(Schedulers.io())//在io线程池中执行map

//将网络的结果转换成我们要的电影名的列表

.map(new Function>() {

@Override

public List apply(MovieBean movieBean) throws Exception {

List array = new ArrayList();

for (int i = 0; i < movieBean.getSubjects().size(); i++) {

String title = movieBean.getSubjects().get(i).getTitle();

array.add(title);

}

return array;

}

})

.observeOn(AndroidSchedulers.mainThread())//在主线程中执行onNext

.subscribe(new Observer>() {

......

@Override

public void onNext(List value) {

ArrayAdapter arrayAdapter = new ArrayAdapter(MovieListActivity.this, android.R.layout.simple_list_item_1, value);

setListAdapter(arrayAdapter);

}

......

});

参考

本人旨在帮助从未接触过RxJava的童鞋直接入坑RxJava2.0,更多使用姿势请自行参考其他资料学习。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 2>>2_RxJava2轻松入门 的相关文章

  • HashMap不写入数据库

    我尝试在我的数据库中写入 但只写入发件人和消息 我不明白为什么会发生这种情况 我认为问题出在我使用 sendMessage 的地方 我认为问题是我没有什么可以做的读 写其他用户的主键 我在数据库中写入消息的活动 public class M
  • 无法解析类型为 xxx 的任何 bean;限定符:[@javax.enterprise.inject.Any()]

    我有一个 LoginProvider 接口 public interface LoginProvider boolean login String username String password 以及两种不同的实现 public clas
  • 使用 GWT CellTableBuilder 构建树表

    Is it possible to build a tree table like this http www sencha com examples ExamplePlace basictreegrid with the new Cell
  • 使用cameltestsupport进行Camel单元测试,模板始终为空

    我正在用 Camel 做一个简单的单元测试 我想做的就是从文件 在资源下 读取 JSON 内容 将其发送到 Java 类进行验证 这是我试图测试的路线 无论我做什么 模板 我用来发送正文 json 始终为空 这是我的代码 public cl
  • 如何在spring mvc中从控制器名称+操作名称获取映射的URL?

    是否有现有的解决方案可以从 Spring MVC3 中的 控制器名称 操作名称 获取映射的 URL 例如 asp net mvc 或 Rails 中的 UrlHelper 我觉得非常有用 thx 也许 你想要这样的东西 in your Co
  • 对话框上的 EditText 不返回任何文本

    我太累了 找不到错误 我没有发现任何错误 但我没有从 editText 收到任何文本 请看下面的代码 活动密码 xml
  • 无法在 Spring Boot 测试中模拟 persistenceContext

    我正在使用带有 Mockito 框架的 spring boot 测试来测试我的应用程序 存储库类 EntityManager 之一作为参考 我的班级如下所示 Repository Transactional Slf4j public cla
  • Firestore - RecycleView - 图像持有者

    我不知道如何编写图像的支架 我已经设置了 2 个文本 但我不知道图像的支架应该是什么样子 你能帮我告诉我图像的文字应该是什么样子才能正确显示吗 holder artistImage setImageResource model getArt
  • 如何从 Retrofit2 获取字符串响应?

    我正在做 android 正在寻找一种方法来执行超级基本的 http GET POST 请求 我不断收到错误 java lang IllegalArgumentException Unable to create converter for
  • Java 8 中函数式接口的使用

    这是来自的后续问题Java 8 中的 双冒号 运算符 https stackoverflow com questions 20001427 double colon operator in java 8其中 Java 允许您使用以下方式引用
  • 在 Spring Boot Actuator 健康检查 API 中启用日志记录

    我正在使用 Spring boot Actuator APIproject https imobilenumbertracker com 拥有一个健康检查端点 并通过以下方式启用它 management endpoints web base
  • Android Studio 将音乐文件读取为文本文件,如何恢复它?

    gameAlert mp3是我的声音文件 运行应用程序时 它询问我该文件不与任何文件类型关联 请定义关联 我选择TextFile错误地 现在我的音乐文件被读取为文本文件 我如何将其转换回music file protected void o
  • 将图像添加到自定义 AlertDialog

    我制作了一个 AlertDialog 让用户可以从我显示的 4 个选项中选择一个 前 3 个让他们在单击号码时直接拨打号码 第 4 个显示不同的视图 现在看起来是这样的 由于第四个选项的目的是不同的任务 我想让它看起来不同 因为用户可能会感
  • 解决错误javax.mail.AuthenticationFailedException

    我不熟悉java中发送邮件的这个功能 我在发送电子邮件重置密码时遇到错误 希望你能给我一个解决方案 下面是我的代码 public synchronized static boolean sendMailAdvance String emai
  • 如何在Java中正确删除数组[重复]

    这个问题在这里已经有答案了 我刚接触 Java 4 天 从我搜索过的教程来看 讲师们花费了大量精力来解释如何分配二维数组 例如 如下所示 Foo fooArray new Foo 2 3 但我还没有找到任何解释如何删除它们的信息 从内存的情
  • Java的-XX:+UseMembar参数是什么

    我在各种地方 论坛等 看到这个参数 并且常见的答案是它有助于高并发服务器 尽管如此 我还是找不到 sun 的官方文档来解释它的作用 另外 它是Java 6中添加的还是Java 5中存在的 顺便说一句 许多热点虚拟机参数的好地方是这一页 ht
  • Java:多线程内的 XA 事务传播

    我如何使用事务管理器 例如Bitronix http docs codehaus org display BTM Home JBoss TS http www jboss org jbosstm or Atomikos http www a
  • Android - 9 补丁

    我正在尝试使用 9 块图片创建一个新的微调器背景 我尝试了很多方法来获得完美的图像 但都失败了 s Here is my 9 patch 当我用Draw 9 patch模拟时 内容看起来不错 但是带有箭头的部分没有显示 或者当它显示时 这部
  • Hibernate 和可序列化实体

    有谁知道是否有一个框架能够从实体类中剥离 Hibernate 集合以使它们可序列化 我查看了 BeanLib 但它似乎只进行实体的深层复制 而不允许我为实体类中的集合类型指定实现映射 BeanLib 目前不适用于 Hibernate 3 5
  • JAXB - 列表<可序列化>?

    我使用 xjc 制作了一些课程 public class MyType XmlElementRefs XmlElementRef name MyInnerType type JAXBElement class required false

随机推荐