RxAndroid结合Retrofit,看看谁才是最佳拍档!

这篇博文酝酿很久了,今天终于下定决心开始写!RxAndroid和Retrofit都算是当下很是流行的Android开发框架,这两个框架光是单独使用就已经爽歪歪了,那么将RxAndroid和Retrofit结合起来,又会有怎样的效果呢?java

鉴于不少小伙伴可能还没用过RxJava或者RxAndroid,因此我打算先来介绍一下RxJava和RxAndroid,而后再来介绍RxAndroid和Retrofit组合拳!!react

本文主要包括如下三方面内容:android

1.RxJava简介git

2.RxJava在Android中的使用github

3.RxJava配合Retrofit的使用web

OK,废话很少说,那就开始吧!编程

1.RxJava简介

RxJava做为Android开发者的新宠已经有很长一段时间了,用过RxJava的人,都以为这个东西简单好用,没用过的小伙伴第一次看到RxJava的代码时可能会以为这个东西很是繁琐,那么今天,我想经过几个简单的非HelloWorld的案例来让你们完全理解RxJava的使用。api

先来看看RxJava的GitHub地址:数组

https://github.com/ReactiveX/RxJava网络

将RxJava引入到咱们的项目中:

compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.0'

那么学习RxJava,先得弄清楚什么是RxJava,关于RxJava的介绍,GitHub上有一句话,

a library for composing asynchronous and event-based programs by using observable sequences.

翻译成中文就是:

RxJava是一个基于可观测序列组成的异步的、基于事件的库。通俗一点说就是RxJava它是一个异步库,这个异步库可让咱们用很是简洁的代码来处理复杂数据流或者事件。OK,那么这是对RxJava的一个基本介绍,接下来咱们再来看看RxJava中两个最最基础的概念,一个是Observable,还有一个是Observer,其中Observable咱们称之为被观察者,Observer称之为观察者,Observable用户发送消息,而Observer用于消费消息,在实际开发中,咱们更多的是选择Observer的一个子类Subscriber来消费消息。在消息发送的过程当中,Observable能够发送任意数量任意类型的消息(甚至一个将一个触摸事件看成一个消息发出),当Observable所发送的消息被成功处理或者消息出错时,一个流程结束。Observable会用它的每个Subscriber(观察者)的onNext方法进行消息处理,在消息成功处理后以onComplete()方法结束流程,若是消息在处理的过程当中出现了任何异常,则以onError()方法结束流程。好比下面几行代码:

Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("哈哈哈哈");
                subscriber.onNext("lalalala");
                subscriber.onCompleted();
            }
        })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {
                        Log.d("google_lenve_fb", "onCompleted: onCompleted()");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("google_lenve_fb", "onError:onError() ");
                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

经过调用Observable的create方法来建立一个消息源,在它的onCall方法调用next方法来发送两条消息,当两条消息发送完成以后,调用onComplete方法表示消息发送完毕!subscribe表示订阅一条消息,在订阅的时候咱们能够传入一个Observer对象,也能够传入一个Subscriber对象,这两个对象中的方法都是同样的,在onNext方法中处理消息,当消息处理完成以后会自动的调用onComplete方法,若是消息处理过程当中出错,则会调用onError方法,上面方法打印的日志以下:

onNext: 哈哈哈哈
onNext: lalalala
onCompleted: onCompleted()

若是我在onNext方法执行一行  1/0 ,onNext方法改为下面的样子:

@Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                        int i = 1 / 0;
                    }

这个时候再运行,系统打印的日志以下:

onNext: 哈哈哈哈
onError:onError() 

当第一条消息打印出来以后,执行1/0时抛异常,直接调用了onError方法,第二条消息将再也不处理。OK,上面的代码是一个小小的案例,RxJava中还有许多好玩的操做符,咱们接下来一个一个来看。

在实际开发中,咱们的数据来源多是多种多样的,为了简化数据操做,Observable类为咱们提供了许多现成的方法,这些方法都可以极大的简化咱们对数据的操做,一个一个来看吧。

1.1 from函数

Observale中的from函数接受一个数组,这个方法返回一个按数组元素的顺序来发射这些数据的Observale,看看下面一行代码:

Observable.from(new String[]{"竹外桃花三两枝", "春江水暖鸭先知"})
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

这里的观察者我使用了Subscriber,它是Observer的一个实现类。这里打印的结果以下:

D/google_lenve_fb: onNext: 竹外桃花三两枝
D/google_lenve_fb: onNext: 春江水暖鸭先知

按顺序将from函数中数组的值一个一个打印出来了。OK,接着往下看:

1.2  just函数

just函数它接受最多10个参数,返回一个按参数顺序发射这些数据的Observable,代码以下:

Observable.just("Hello", "World", "Hello", "RxJava!","塞外秋来风景异","衡阳雁去无留意"
        ,"四面边声连角起","千嶂里","长烟落日孤城闭","浊酒一杯家万里")
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

打印结果以下:

D/google_lenve_fb: onNext: Hello
D/google_lenve_fb: onNext: World
D/google_lenve_fb: onNext: Hello
D/google_lenve_fb: onNext: RxJava!
D/google_lenve_fb: onNext: 塞外秋来风景异
D/google_lenve_fb: onNext: 衡阳雁去无留意
D/google_lenve_fb: onNext: 四面边声连角起
D/google_lenve_fb: onNext: 千嶂里
D/google_lenve_fb: onNext: 长烟落日孤城闭
D/google_lenve_fb: onNext: 浊酒一杯家万里

1.3map函数

map函数能够对Observable建立的原始数据进行二次加工,而后再被观察者获取。好比下面一段代码,我给原始数据的每一项都追加一个字符串,而后返回:

Observable.from(new String[]{"醉里挑灯看剑","梦回吹角连营"})
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        return s + "---辛弃疾";
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve_fb", "onNext: " + s);
                    }
                });

打印结果以下:

D/google_lenve_fb: onNext: 醉里挑灯看剑---辛弃疾
D/google_lenve_fb: onNext: 梦回吹角连营---辛弃疾

RxJava的使用都是链式编程,使用map函数时数据来源能够各类各样。

1.4flatMap函数

flatMap函数接受一个Observable函数做为输入函数,而后在这个输入的基础上再建立一个新的Observable进行输出,好比下面一段代码:

Observable.just("落霞与孤鹜齐飞", "秋水共长天一色")
                .flatMap(new Func1<String, Observable<String>>() {
                    @Override
                    public Observable<String> call(String s) {
                        return Observable.from(new  String[]{s + "冯唐易老", s + "李广难封"});
                    }
                }).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                Log.d("google_lenve_fb", "onNext: " + s);
            }
        });

打印结果:

D/google_lenve_fb: onNext: 落霞与孤鹜齐飞冯唐易老
D/google_lenve_fb: onNext: 落霞与孤鹜齐飞李广难封
D/google_lenve_fb: onNext: 秋水共长天一色冯唐易老
D/google_lenve_fb: onNext: 秋水共长天一色李广难封

1.5 scan函数

scan函数是一个累加器函数,对于Observable发射的每项数据进行累加,并将累加的结果返回,以下:

Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                .scan(new Func2<Integer, Integer, Integer>() {
                    @Override
                    public Integer call(Integer integer, Integer integer2) {
                        return integer + integer2;
                    }
                })
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d("google_lenve_fb", "onNext: " + integer);
                    }
                });
        Observable.from(new String[]{"明", "月", "别", "枝", "惊", "鹊"})
                .scan(new Func2<String, String, String>() {
                    @Override
                    public String call(String s, String s2) {
                        return s + s2;
                    }
                })
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve", "onNext: " + s);
                    }
                });

打印结果以下:

D/google_lenve_fb: onNext: 1
D/google_lenve_fb: onNext: 3
D/google_lenve_fb: onNext: 6
D/google_lenve_fb: onNext: 10
D/google_lenve_fb: onNext: 15
D/google_lenve_fb: onNext: 21
D/google_lenve_fb: onNext: 28
D/google_lenve_fb: onNext: 36
D/google_lenve_fb: onNext: 45
D/google_lenve_fb: onNext: 55
D/google_lenve: onNext: 明
D/google_lenve: onNext: 明月
D/google_lenve: onNext: 明月别
D/google_lenve: onNext: 明月别枝
D/google_lenve: onNext: 明月别枝惊
D/google_lenve: onNext: 明月别枝惊鹊

1.6elementAt函数

elementAt函数表示获取数据源中的第N项数据输出,以下:

 Observable.just("清", "风", "半", "夜", "鸣", "蝉")
                .elementAt(4)
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve", "onNext: "+s);
                    }
                });

打印结果以下:

D/google_lenve: onNext: 鸣

1.7merge函数

merge函数能够用来合并多个Observable数据源,而后将合并后的数据在一块儿输出,以下:

Observable<String> observable1 = Observable.just("十里楼台倚翠薇", "百花深处杜鹃啼");
        Observable<String> observable2 = Observable.just("殷勤自与行人语","不似流莺取次飞");
        Observable.merge(observable1, observable2)
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("google_lenve", "onNext: "+s);
                    }
                });

打印结果以下:

D/google_lenve: onNext: 十里楼台倚翠薇
D/google_lenve: onNext: 百花深处杜鹃啼
D/google_lenve: onNext: 殷勤自与行人语
D/google_lenve: onNext: 不似流莺取次飞

1.8 zip函数

zip函数用来合并多个Observable的数据源,可是与merge不一样的是,zip函数中能够对数据源进行二次操做,而不是简单的合并,代码以下:

Observable<String> observable1 = Observable.just("十里楼台倚翠薇", "百花深处杜鹃啼");
        Observable<String> observable2 = Observable.just("问君能有几多愁","恰似一江春水向东流");
        Observable.zip(observable1, observable2, new Func2<String, String, Object>() {
            @Override
            public Object call(String s, String s2) {
                return s+s2;
            }
        })
        .subscribe(new Subscriber<Object>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Object o) {
                Log.d("google_lenve", "onNext: "+o.toString());
            }
        });

打印日志以下:

D/google_lenve: onNext: 十里楼台倚翠薇问君能有几多愁
D/google_lenve: onNext: 百花深处杜鹃啼恰似一江春水向东流

1.9其余的过滤函数

Observable函数中还有其余一些好用的过滤函数,我就再也不一一演示了,小伙伴们看下面的代码自行试验便可:

    private void m7() {
        Observable.just(10, 12, 13, 14, 15, 16, 16, 16, 17, 18)
            //在数据序列的开头插入一条指定的项1
                .startWith(2)
                .filter(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer > 0;
                    }
                })
            //只发射前N个元素
                .take(2)
            //只发射最后N个元素
                .takeLast(2)
            //只发射第一个元素
                .first()
            //只发射最后一个元素
                .last()
            //跳过前两个
                .skip(2)
                //跳过最后两个
                .skipLast(2)
                //数据过滤,过滤掉重复数据
                .distinct()
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d("google_lenve_fb", "onNext: " + integer);
                    }
                });

1.10 subscribeOn函数和observeOn函数

这两个函数在咱们Android开发中仍是很是有用的,其中subscribeOn表示指定被观察者执行的线程,而observeOn则表示观察者执行的线程,这个解决网络访问仍是很是方便的,以下:

Observable<String> observable1 = Observable.just("十里楼台倚翠薇", "百花深处杜鹃啼");
        Observable<String> observable2 = Observable.just("问君能有几多愁","恰似一江春水向东流");
        Observable.zip(observable1, observable2, new Func2<String, String, Object>() {
            @Override
            public Object call(String s, String s2) {
                Log.d("google_lenve", "call: "+Thread.currentThread().getName());
                return s+s2;
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<Object>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Object o) {
                Log.d("google_lenve", "onNext: "+Thread.currentThread().getName()+"--------"+o.toString());
            }
        });

打印日志以下:

D/google_lenve: call: RxCachedThreadScheduler-1
D/google_lenve: call: RxCachedThreadScheduler-1
 D/google_lenve: onNext: main--------十里楼台倚翠薇问君能有几多愁
 D/google_lenve: onNext: main--------百花深处杜鹃啼恰似一江春水向东流


2.RxJava在Android中的使用

RxJava在安卓开发中不只可以处理简单的数据流,最好玩的地方莫过于网络访问,我举一个例子(其余的数据流处理这里就再也不介绍了),好比我有一个按钮,点击该按钮加载一张图片出来,代码以下:

Observable.create(new Observable.OnSubscribe<Bitmap>() {
            @Override
            public void call(Subscriber<? super Bitmap> subscriber) {
                subscriber.onNext(getBitmap());
            }
        })
                //设置数据加载在子线程进行
                .subscribeOn(Schedulers.io())
                //设置图片加载在主线程进行
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Bitmap>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Bitmap bitmap) {
                        iv.setImageBitmap(bitmap);
                    }
                });

getBitmap方法以下:

private Bitmap getBitmap() {
        HttpURLConnection con;
        try {
            URL url = new URL("http://img3.cache.netease.com/photo/0008/2016-08-10/BU4A81A72ODN0008.550x.0.jpg");
            con = (HttpURLConnection) url.openConnection();
            con.setConnectTimeout(5 * 1000);
            con.connect();
            if (con.getResponseCode() == 200) {
                return BitmapFactory.decodeStream(con.getInputStream());
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

有没有感受爽歪歪呢?今后完全告别Handler,告别new Thread。。。。。

3.RxJava配合Retrofit的使用

最后咱们再来看看当下最流行的两个框架的组合使用!若是你还不了解Retrofit的使用,参考我以前的博客一个App带你学会Retrofit2.0,麻麻不再用担忧个人网络请求了!


将RxJava和Retrofit结合的时候,首先先修改gradle文件,先把个人gradle文件拿出来给你们瞧瞧:

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.0'

APIService中的定义以下:

public interface APIService {
    @GET("api/lore/classify")
    Observable<ClassfyBean> getClassfyBean();
}

建立Retrofit同时建立APIService的实例,代码以下:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.tngou.net")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        APIService apiService = retrofit.create(APIService.class);

注意,这里和咱们在通常场景下使用Retrofit有一个区别,那就是多了addCallAdapterFactory这个方法,这里咱们添加的RxJava的适配工厂。而后咱们就能够调用APIService中的方法来访问网络数据了,以下:

                observable
                //在子线程访问数据
                .subscribeOn(Schedulers.io())
                //在主线程显示数据
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<ClassfyBean>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable throwable) {

                    }

                    @Override
                    public void onNext(ClassfyBean classfyBean) {
                        StringBuffer sb = new StringBuffer();
                        for (ClassfyBean.TngouBean tngouBean : classfyBean.getTngou()) {
                            sb.append(tngouBean.getName() + "\n");
                        }
                        tv.setText(sb.toString());
                    }
                });

OK,这才是网络访问和数据处理最佳拍档。

今天先这样,后面再找时间详细介绍这两个结合的条条框框。。。。


以上。



另外推荐两篇大神文章:

http://wuxiaolong.me/2016/01/18/rxjava/

http://gank.io/post/560e15be2dca930e00da1083

相关文章
相关标签/搜索