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轻松入门 的相关文章

  • Eclipse 在源代码管理中保存操作

    我们希望找到一种在签入之前执行代码标准的 轻量级 方法 我们真的很喜欢使用 Eclipse 内置的想法保存操作 go to Preferences gt gt Java gt gt Editor gt gt Save Actions 其中有
  • 如何在android上的python kivy中关闭应用程序后使服务继续工作

    我希望我的服务在关闭应用程序后继续工作 但我做不到 我听说我应该使用startForeground 但如何在Python中做到这一点呢 应用程序代码 from kivy app import App from kivy uix floatl
  • 是什么决定了从 lambda 创建哪个函数式接口?

    请考虑这个例子 import java util function Consumer public class Example public static void main String args Example example new
  • SAML 服务提供商 Spring Security

    当使用预先配置的服务提供者元数据时 在 Spring Security 中 是否应该有 2 个用于扩展元数据委托的 bean 定义 一份用于 IDP 元数据 一份用于 SP 元数据
  • Java:如何从转义的 URL 获取文件?

    我收到了一个定位本地文件的 URL 事实上我收到的 URL 不在我的控制范围内 URL 按照 RFC2396 中的定义进行有效转义 如何将其转换为 Java File 对象 有趣的是 URL getFile 方法返回一个字符串 而不是文件
  • 如何在不超过最大值的情况下增加变量?

    我正在为学校开发一个简单的视频游戏程序 我创建了一个方法 如果调用该方法 玩家将获得 15 点生命值 我必须将生命值保持在最大值 100 并且由于我目前的编程能力有限 我正在做这样的事情 public void getHealed if h
  • Cassandra java驱动程序协议版本和连接限制不匹配

    我使用的java驱动程序版本 2 1 4卡桑德拉版本 dsc cassandra 2 1 10cql 的输出给出以下内容 cqlsh 5 0 1 Cassandra 2 1 10 CQL spec 3 2 1 Native protocol
  • 画透明圆,外面填充

    我有一个地图视图 我想在其上画一个圆圈以聚焦于给定区域 但我希望圆圈倒转 也就是说 圆的内部不是被填充 而是透明的 其他所有部分都被填充 请参阅这张图片了解我的意思 http i imgur com zxIMZ png 上半部分显示了我可以
  • Hazelcast 分布式锁与 iMap

    我们目前使用 Hazelcast 3 1 5 我有一个简单的分布式锁定机制 应该可以跨多个 JVM 节点提供线程安全性 代码非常简单 private static HazelcastInstance hInst getHazelcastIn
  • hibernate锁等待超时超时;

    我正在使用 Hibernate 尝试模拟对数据库中同一行的 2 个并发更新 编辑 我将 em1 getTransaction commit 移至 em1 flush 之后我没有收到任何 StaleObjectException 两个事务已成
  • 很好地处理数据库约束错误

    再一次 它应该很简单 我的任务是在我们的应用程序的域对象中放置一个具有唯一约束的特定字段 这本身并不是一个很大的挑战 我刚刚做了以下事情 public class Location more fields Column unique tru
  • 有没有一种快速方法可以从 Jar/war 中删除文件,而无需提取 jar 并重新创建它?

    所以我需要从 jar war 文件中删除一个文件 我希望有类似 jar d myjar jar file I donot need txt 的内容 但现在我能看到从 Linux 命令行执行此操作的唯一方法 不使用 WinRAR Winzip
  • Java整数双除法混淆[重复]

    这个问题在这里已经有答案了 方案1 int sum 30 double avg sum 4 result is 7 0 not 7 5 VS 方案2 int sum 30 double avg sum 4 0 Prints lns 7 5
  • 欧洲中部时间 14 日 3 月 30 日星期五 00:00:00 至 日/月/年

    我尝试解析格式日期Fri Mar 30 00 00 00 CET 14至 日 月 年 这是我的代码 SimpleDateFormat formatter new SimpleDateFormat dd MM yyyy System out
  • spring中如何使用jackson代替JdkSerializationRedisSerializer

    我在我的一个 Java 应用程序中使用 Redis 并且正在序列化要存储在 Redis 中的对象列表 但是 我注意到使用 RedisTemplate 会使用 JdkSerializationRedisSerializer 相反 我想使用 J
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • 为什么这个作业不起作用?

    我有课Results which extends ArrayList
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • 调整添加的绘制组件的大小和奇怪的摆动行为

    这个问题困扰了我好几天 我正在制作一个特殊的绘画程序 我制作了一个 JPanel 并添加了使用 Paint 方法绘制的自定义 jComponent 问题是 每当我调整窗口大小时 所有添加的组件都会 消失 或者只是不绘制 因此我最终会得到一个
  • GUI Java 程序 - 绘图程序

    我一直试图找出我的代码有什么问题 这个想法是创建一个小的 Paint 程序并具有红色 绿色 蓝色和透明按钮 我拥有我能想到的让它工作的一切 但无法弄清楚代码有什么问题 该程序打开 然后立即关闭 import java awt import

随机推荐