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就是这么简单,就是这样简洁,就是这么异步,额,这个异步吗,只要你想,就一定可以实现,通过以上简单的用法示例,现总结流程如下:
这里写图片描述

总结不一定准确,但是我理解就行了,嘎嘎!

0 0
原创粉丝点击