RxJava使用方法简析
来源:互联网 发布:java spring框架 实例 编辑:程序博客网 时间:2024/06/05 11:47
我们很懒,所以我们就开发了很多很多的框架,用来节省我们的工作量、工作时间。异步操作难免是避不开的,官方提供的Handler机制以及AsyncTask ,都能实现异步操作,但是代码随着逻辑的增多而变得复杂,看上去混乱不堪有时候简直,所以,简洁高效的代码也是我们的追求。因此,为了异步,为了简洁,RxJava应运而生,来解决了以上的问题。
1.RxJava 地址以及添加
github地址:
https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
依赖库添加:
compile ‘io.reactivex:rxjava:1.1.6’
compile ‘io.reactivex:rxandroid:1.2.1’
2.RxJava的用法示例
RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。
与传统观察者模式不同, RxJava 的事件回调方法除了普通事件 onNext() (相当于 onClick() / onEvent())之外,还定义了两个特殊的事件:onCompleted() 和 onError()。
onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
2-1:基本实现
先来看一下最基础的用法,
Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.d(TAG, "call: threadId:"+Thread.currentThread().getId()); subscriber.onStart(); subscriber.onNext("Hello World!"); subscriber.onCompleted(); } }) .subscribe(new Observer<String>() { @Override public void onCompleted() { Log.d(TAG, "onCompleted: threadId:"+Thread.currentThread().getId()); } @Override public void onError(Throwable e) { Log.e(TAG, "onError: threadId:"+Thread.currentThread().getId()); } @Override public void onNext(String s) { Log.d(TAG, "onNext: threadId:"+Thread.currentThread().getId()); Log.i(TAG, "onNext: s = "+s); } });
打印的结果如下所示:
09-03 11:43:57.322 16813-16813/? D/RxIavaDemo: call: threadId:109-03 11:43:57.322 16813-16813/? D/RxIavaDemo: onNext: threadId:109-03 11:43:57.322 16813-16813/? I/RxIavaDemo: onNext: s = Hello World!09-03 11:43:57.322 16813-16813/? D/RxIavaDemo: onCompleted: threadId:1
从上可以看出,事件的处理和结果的接收都是在同一个线程里面处理的。但是,Rxjava的意义何在,异步呢?别急,看以下代码的处理,你就会发现了,异步原来是这么的简单。
Log.i(TAG, "testFunction: threadId:"+Thread.currentThread().getId()); Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.d(TAG, "call: threadId:"+Thread.currentThread().getId()); subscriber.onStart(); subscriber.onNext("Hello World!"); subscriber.onCompleted(); }}) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<String>() { @Override public void onCompleted() { Log.d(TAG, "onCompleted: threadId:" + Thread.currentThread().getId()); } @Override public void onError(Throwable e) { Log.e(TAG, "onError: threadId:" + Thread.currentThread().getId()); } @Override public void onNext(String s) { Log.d(TAG, "onNext: threadId:" + Thread.currentThread().getId()); Log.i(TAG, "onNext: s = " + s); } });
对比以上代码,我们简简单单的添加了两行代码:
.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())
那么接下俩看以下打印的结果如何:
09-03 11:51:11.354 18454-18454/? I/RxIavaDemo: testFunction: threadId:109-03 11:51:11.413 18454-18484/? D/RxIavaDemo: call: threadId:2407609-03 11:51:11.444 18454-18454/? D/RxIavaDemo: onNext: threadId:109-03 11:51:11.444 18454-18454/? I/RxIavaDemo: onNext: s = Hello World!09-03 11:51:11.444 18454-18454/? D/RxIavaDemo: onCompleted: threadId:1
看见了没,第二行threadId与其它的threadId很明显的不一样啊,说明我们在处理事件的时候,发生在了一个新的线程里面,而结果的接收,还是在主线程里面操作的。怎么样,只要添加两句话,异步立马就实现了,异步处理耗时操作,就是这么easy。
以上是RxJava的很基础很简单的一个用法,那么我们接着往下看,比如我们有一组需求把一个String数组的字符串,单个打印出来,我们用Rxjava怎么实现呢?看代码:
Log.i(TAG, "testFunction: threadId:"+Thread.currentThread().getId()); Observable.from(new String[]{"one","two","three","four"}) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<String>() { @Override public void onCompleted() { Log.d(TAG, "onCompleted: threadId:" + Thread.currentThread().getId()); } @Override public void onError(Throwable e) { Log.e(TAG, "onError: threadId:" + Thread.currentThread().getId()); } @Override public void onNext(String s) { Log.i(TAG, "onNext: s = " + s); } });
Observable的from方法是给我们封装好的,我们直接拿来用就可以了。具体参数含义以后再说,打印的结果看下:
09-03 11:59:40.799 20463-20463/? I/RxIavaDemo: testFunction: threadId:109-03 11:59:40.838 20463-20463/? I/RxIavaDemo: onNext: s = one09-03 11:59:40.838 20463-20463/? I/RxIavaDemo: onNext: s = two09-03 11:59:40.838 20463-20463/? I/RxIavaDemo: onNext: s = three09-03 11:59:40.838 20463-20463/? I/RxIavaDemo: onNext: s = four09-03 11:59:40.838 20463-20463/? D/RxIavaDemo: onCompleted: threadId:1
再来看一个官方提供的方法:
Log.i(TAG, "testFunction: threadId:"+Thread.currentThread().getId()); Observable.just("one","two","three","four") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<String>() { @Override public void onCompleted() { Log.d(TAG, "onCompleted: threadId:" + Thread.currentThread().getId()); } @Override public void onError(Throwable e) { Log.e(TAG, "onError: threadId:" + Thread.currentThread().getId()); } @Override public void onNext(String s) { Log.i(TAG, "onNext: s = " + s); } });
打印结果如下:
09-03 14:06:32.051 9822-9822/? I/RxIavaDemo: testFunction: threadId:109-03 14:06:32.089 9822-9822/? I/RxIavaDemo: onNext: s = one09-03 14:06:32.089 9822-9822/? I/RxIavaDemo: onNext: s = two09-03 14:06:32.089 9822-9822/? I/RxIavaDemo: onNext: s = three09-03 14:06:32.089 9822-9822/? I/RxIavaDemo: onNext: s = four09-03 14:06:32.089 9822-9822/? D/RxIavaDemo: onCompleted: threadId:1
和上面的from一样,结果并无二致。
2-2:转换
以上的都是小儿科,现在最牛逼的地方来了。比如说,我想把一组字符串{“1”,“2”,“3”,“4”}转成int类型,该咋办呢?别急,看Rxjava是如何做到的,
Log.i(TAG, "testFunction: threadId:"+Thread.currentThread().getId()); Observable.just("1","2","3","4") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(new Func1<String, Integer>() { @Override public Integer call(String s) { return Integer.parseInt(s); } }) .subscribe(new Action1<Integer>() { @Override public void call(Integer integer) { Log.i(TAG, "call: integer = "+integer); } });
很简单,添加一个map函数,在里面做string—>int类型的转换。下面看一下打印结果如何:
09-03 14:17:42.964 11974-11974/? I/RxIavaDemo: testFunction: threadId:109-03 14:17:43.002 11974-11974/? I/RxIavaDemo: call: integer = 109-03 14:17:43.002 11974-11974/? I/RxIavaDemo: call: integer = 209-03 14:17:43.002 11974-11974/? I/RxIavaDemo: call: integer = 309-03 14:17:43.002 11974-11974/? I/RxIavaDemo: call: integer = 4
map转换,是一对一的转换,像示例当中,我们把string转成int,但是当我们需要一对多的转换,该怎么做呢?比如说,定义一个学生类:Student.java:
public class Student{ private String name; private List<String> courses; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getCourses() { return courses; } public void setCourses(List<String> courses) { this.courses = courses; } }
里面定义了学生的名字,以及学生需要学习的课程数组。这个时候,我要打印课程列表的时候,该怎么办呢?首先,你可能会这样,
Student student1 = new Student(); student1.setName("Dandy"); List<String> courses = new ArrayList<>(); courses.add("语文"); courses.add("数学"); courses.add("英语"); student1.setCourses(courses); Student student2 = new Student(); student2.setName("Seeker"); List<String> courses2 = new ArrayList<>(); courses2.add("化学"); courses2.add("地理"); courses2.add("政治"); student2.setCourses(courses2); Observable.just(student1,student2) .subscribe(new Action1<Student>() { @Override public void call(Student student) { Log.i(TAG, "call: name = "+student.getName()); List<String> course = student.getCourses(); for(String str:course){ Log.i(TAG, "call: str = "+str); } } });
打印的结果如下:
09-03 14:44:30.318 16819-16819/? I/RxIavaDemo: testFunction: threadId:109-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: name = Dandy09-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: str = 语文09-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: str = 数学09-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: str = 英语09-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: name = Seeker09-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: str = 化学09-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: str = 地理09-03 14:44:30.325 16819-16819/? I/RxIavaDemo: call: str = 政治
到时候想了,我不想执行一个for循环,该怎么办呢?上面提到的,转换,对了,我们做转换不就成,简单的通俗的一点理解,我转换一次,是list,那么我再转换一次不就是string了吗,怎么写呢?看下嘛:
Observable.just(student1,student2) .flatMap(new Func1<Student, Observable<String>>() { @Override public Observable<String> call(Student student) { return Observable.from(student.getCourses()); } }) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.i(TAG, "call: s = "+s); } });
这里我们用到了flatmap这一函数,按通俗的一点理解:我们首先把Student转成了Observable,然后呢,又把student.getCourses()转成string挨个打印出来,结果如下:
09-03 14:54:30.340 18833-18833/? I/RxIavaDemo: testFunction: threadId:109-03 14:54:30.359 18833-18833/? I/RxIavaDemo: call: s = 语文09-03 14:54:30.359 18833-18833/? I/RxIavaDemo: call: s = 数学09-03 14:54:30.359 18833-18833/? I/RxIavaDemo: call: s = 英语09-03 14:54:30.359 18833-18833/? I/RxIavaDemo: call: s = 化学09-03 14:54:30.359 18833-18833/? I/RxIavaDemo: call: s = 地理09-03 14:54:30.359 18833-18833/? I/RxIavaDemo: call: s = 政治
显然,我们要实现的功能做到了。
RxJava就是这么简单,就是这样简洁,就是这么异步,额,这个异步吗,只要你想,就一定可以实现,通过以上简单的用法示例,现总结流程如下:
总结不一定准确,但是我理解就行了,嘎嘎!
- RxJava使用方法简析
- RxJava的基本使用方法
- Android Rxjava使用方法
- RXJava的简析
- RxJava多种常用场景使用方法
- MVP+Retrofit2+RxJava使用方法demo
- rxjava+rxandroid+retrofit2.0使用方法demo讲解
- fastjson使用方法简析
- fragment使用方法简析
- RXjava 深入简出
- rxjava
- RXJava
- RXJava
- RXJava
- RxJava
- Rxjava
- RxJava
- RxJava
- Android GridView自适应Item高度
- SQL Server分页存储过程
- 测试Hadoop2.7.1
- App第三方登录微信遇到code以及无法弹出微信登录界面libs包不对等一系列问题解决
- mysql遍历字符串,按ASCII码拼接返回数字
- RxJava使用方法简析
- 移植u-boot学习笔记1-----实验及分析启动过程之概述
- H.264句法和语法总结(七)加权预测句法
- 前端工程师手册
- 51Nod1019 求逆序数(归并排序)
- Android图片保存在本地相册
- 巧妙地批量修改unity本地文件的参数
- 整合Kafka到Spark Streaming——代码示例和挑战
- H.264句法和语法总结(八)参考图像序列标记 (marking)操作的语义