RxJava & Retrofit 初探

来源:互联网 发布:导入数据load from 编辑:程序博客网 时间:2024/05/16 05:44

年后一直想学习新的技术,但是公司项目一直很紧,没有太多时间去学习,只能晚上回去后看一点,零零碎碎的学习总是容易忘记,还是博客记录一下比较好。2017加油!!

RxJava是什么

  • 一个实现异步操作的库。

  • RxJava 的异步实现,是通过一种扩展的观察者模式来实现的。

  • 一个响应式编程框架。

  • 无论逻辑多复杂,都能保持代码的简洁度。

观察者模式

举个栗子,拿订报纸来说,订阅报纸的人(观察者)订阅了人民日报(建立订阅关系),人民日报报社(被观察者)出版新报纸就会向订报纸的人发报纸(发送事件)。

  • RxJava 的观察者模式

RxJava 有四个基本概念:Observable (被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。

Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。

这里写图片描述

RxJava响应式编程

响应式编程就是与异步数据流交互的编程范式。

单击事件就是一个异步事件流,你可以观察这个流,也可以基于这个流做一些自定义操作。响应式就是基于这种想法。你能够创建所有事物的数据流,而不仅仅只是单击和悬停事件数据流。

最重要的是,有一堆的函数能够创建(create)任何流,也能将任何流进行组合(combine)和过滤(filter)。 这正是“函数式”的魔力所在。一个流能作为另一个流的输入(input),甚至多个流也可以作为其它流的输入。你能合并(merge)两个流。你还能通过过滤(filter)一个流得到那些你感兴趣的事件。你能将一个流中的数据映射(map)到一个新的流中。

流是整个响应式编程体系中的核心!!

举个栗子,有一条生产手机的流水线,若干流水线的操作工,还有一个对生产结果感兴趣的产品经理。产品经理启动流水线,操作工对拿到的材料进行各种处理,添点零部件呀什么的,最后给产品经理。

可以抽象出来一个流程:

原料 ——>操作工1—–>操作工2—–>…..操作工n–>产品经理

Observable -> Operator 1 -> Operator 2 -> Operator 3 -> Subscriber

  • 操作工-> 操作符。既要各司其职的完成各种工作,同时也要保证事件的处理
    永远处于流水线上,这也是RxJava响应式编程的关键点。

  • subscribe() 让一个 Observer (即观察者)去订阅一个 Observable。若没有这一步整个流水线都无法启动。

  • 需要最大程度的确保产品经理已经完成的工作不需要再做修改,Subscriber 的工作量尽量小。

基本使用

创建观察者

  • 创建Observer ,即观察者,它决定事件触发的时候将有怎样的行为。
        Observer observer= new Observer<String>() {            @Override            public void onCompleted() {            }            @Override            public void onError(Throwable e) {                Log.d(TAG,e.getMessage);            }            @Override            public void onNext(String s) {                Log.d(TAG,s);            }        };
  • 创建Subscriber

RxJava还内置了一个实现了 Observer 的抽象类:Subscriber 。

        Subscriber subscriber= new Subscriber<String>() {            @Override            public void onCompleted() {            }            @Override            public void onError(Throwable e) {                Log.d(TAG,e.getMessage());            }            @Override            public void onNext(String s) {                Log.d(TAG,s);            }        };        };

Subscriber 对 Observer 接口进行了一些扩展,在 subscribe 过程中,Observer 会先被转换成一个 Subscriber 再使用。所以在事件正常触发时执行的是 subscriber 的 onNext 方法,错误时执行的也是 subscriber 的 onError方法 。基本使用时 Observer 和 Subscriber 相同。

创建被观察者 Observable

Observable 决定什么时候触发事件以及触发怎样的事件。

  • 直接使用 create 方法进行创建。

这里传入 OnSubscribe 作为参数,OnSubscribe 会被存储在返回的 Observable 对象中,它的作用相当于一个计划表,当 Observable 被订阅的时候,OnSubscribe 的 call() 方法会自动被调用,事件序列就会依照设定依次触发。

Observable observable=Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(Subscriber<? super String> subscriber) {                subscriber.onNext("Hello");                subscriber.onCompleted();            }        });
  • just(T…): 将传入的参数依次发送出来。
Observable observable = Observable.just("Hello", "Hi", "Aloha");
  • from(T[]) / from(Iterable
String[] words = {"Hello", "Hi", "Aloha"};Observable observable = Observable.from(words);

创建订阅关系 Subscribe

使用 subscribe() 方法即可实现订阅。

observable.subscribe(observer);// 或者:observable.subscribe(subscriber);

建立订阅关系以后,observable 发出事件内容,该例子发出 Hello 字符串,调用的 call 方法是观察者 subscriber 的回调方法,
打印被观察者传递过来的字符串 Hello 。

线程切换

在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用 subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler (调度器)。

下面是几个常用的内置的 Scheduler :

  • Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
  • Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。
  • Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
  • Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。

使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制。

  • subscribeOn(): 指定 subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程,或者叫做事件产生的线程。
  • observeOn(): 指定 Subscriber 所运行在的线程,或者叫做事件消费的线程。
Observable.just(1, 2, 3, 4)    .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程    .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程    .subscribe(new Action1<Integer>() {        @Override        public void call(Integer number) {            Log.d(tag, "number:" + number);        }    });

Observable.just(1, 2, 3, 4)为顺序发出1,2,3,4四个事件,这四个事件都在IO线程发送,打印数字在主线程。subscribeOn(Scheduler.io()) 和 observeOn(AndroidSchedulers.mainThread()) 的使用方式,适用于多数的“后台线程取数据,主线程显示”的程序策略。

特别解释一下 Action1 ,Action1 是 RxJava 的一个接口,它只有一个方法 call(),包含一个参数;由于 onCompleted() 方法也是无参无返回值的,因此 Action1 可以被当成一个包装对象,将 onCompleted() 的内容打包起来将自己作为一个参数传入 subscribe() 以实现不完整定义的回调。

通过 observeOn() 的多次调用,程序实现了线程的多次切换。不过,subscribeOn() 的位置放在哪里都可以,但是只能调用一次。

一行代码切换线程,神奇不?还有更爽的,就是接下来要说的变换。

变换

变换,就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。

  • map

map() 是一对一的转化,将事件A转换为事件B。

这里写图片描述

Observable.just("images/logo.png") // 输入类型 String    .map(new Func1<String, Bitmap>() {        @Override        public Bitmap call(String filePath) { // 参数类型 String            return getBitmapFromPath(filePath); // 返回类型 Bitmap        }    })    .subscribe(new Action1<Bitmap>() {        @Override        public void call(Bitmap bitmap) { // 参数类型 Bitmap            showBitmap(bitmap);        }    });

通过Func1

Student[] students = ...;Subscriber<Course> subscriber = new Subscriber<Course>() {    @Override    public void onNext(Course course) {        Log.d(tag, course.getName());    }    ...};Observable.from(students)    .flatMap(new Func1<Student, Observable<Course>>() {        @Override        public Observable<Course> call(Student student) {            return Observable.from(student.getCourses());        }    })    .subscribe(subscriber);

Observable.from 为输入一个集合 students,每次输出一个集合中的元素 student ,flatMap 将传入的 student 对象创建一个 Observable 对象,该对象并不被传递给 subscriber ,只是激活并发送事件(每个学生修的每一们课),然后将所有的事件都汇给同一个 Observable ,该 Observable 负责将收集到的事件传递给 subscriber 的回调方法。

把事件拆成了两级,通过一组新创建的 Observable 将初始的对象『铺平』之后通过统一路径分发了下去。而这个『铺平』就是 flatMap() 所谓的 flat。

Retrofit

Retrofit就是对okhttp做了一层封装。把网络请求都交给了Okhttp,我们只需要通过简单的配置就能使用retrofit来进行网络请求了。

  • 导包
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'//Retrofit2所需要的包compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'//ConverterFactory的Gson依赖包compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4'//ConverterFactory的String依赖包

假设我们请求的API是:

https://api.douban.com/v2/movie/top250
  • 定义一个接口
public interface MovieService {    @GET("top250")   Call<MovieSubject> getTop250(@Query("count")int count,@Query("start")int start);}
  • 创建一个Retrofit 对象
Retrofit retrofit = new Retrofit.Builder()               .baseUrl("https://api.douban.com/v2/movie/")               //增加返回值为String的支持               .addConverterFactory(ScalarsConverterFactory.create())               //增加返回值为Gson的支持(以实体类返回)               .addConverterFactory(GsonConverterFactory.create())               //增加返回值为Oservable<T>的支持               .addCallAdapterFactory(RxJavaCallAdapterFactory.create())               .build();
  • 生成接口的实例对象
MovieService movieSerive = retrofit.create(RequestSerives.class);
  • 得到Call对象,就可以发出网络请求啦
Call<MovieSubject> call = movieSerive getTop250(0,20);//传入请求参数call.enqueue(new Callback<MovieSubject>() {    @Override    public void onResponse(Call<MovieSubject> call, Response<MovieSubject> response) {    }    @Override    public void onFailure(Call<String> call, Throwable t) {        Log.e("===","失败");    }});

RxJava x Retrofit 实现网络请求

  • 定义一个接口 MovieService,定义一个获取豆瓣电影的方法 getTop250,返回一个Observable对象
@GET("top250")   Observable<MovieSubject> getTop250(@Query("start") int start, @Query("count") int count);
  • 创建一个 retrofit 对象
Retrofit retrofit = new Retrofit.Builder()               .baseUrl("https://api.douban.com/v2/movie/")               //增加返回值为Gson的支持(以实体类返回)               .addConverterFactory(GsonConverterFactory.create())               //增加返回值为Oservable<T>的支持               .addCallAdapterFactory(RxJavaCallAdapterFactory.create())               .build();MovieService service=retrofit.create(MovieService.class);
  • 使用

Retrofit 把请求封装进 Observable ,在请求结束后调用 onNext() 或在请求失败后调用 onError()。

getTop250(0, 20)                .map(new Func1<MovieSubject, List<MovieItem>>() {                    @Override                    public List<MovieItem> call(MovieSubject movieSubject) {                        return movieSubject.getMovieItems();                    }                })                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Subscriber<List<MovieItem>>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                        toast("e.getMessage");                    }                    @Override                    public void onNext(List<MovieItem> movieItems) {                        view.showMovie(movieItems);                    }                });

感谢

  • [给 Android 开发者的 RxJava 详解]
    (http://gank.io/post/560e15be2dca930e00da1083#toc_1)

  • [RxJava 之 响应式编程]
    (http://www.jianshu.com/p/fee2a68da1fc)

  • 深入浅出RxJava一:基础篇

    深入浅出RxJava二:操作符

    深入浅出RxJava三–响应式的好处

    深入浅出RxJava四-在Android中使用响应式编程

0 0
原创粉丝点击