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

鉴于很多小伙伴可能还没用过RxJava或者RxAndroid,所以我打算先来介绍一下RxJava和RxAndroid,然后再来介绍RxAndroid和Retrofit组合拳!!

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

1.RxJava简介

2.RxJava在Android中的使用

3.RxJava配合Retrofit的使用

OK,废话不多说,那就开始吧!

1.RxJava简介

RxJava作为Android开发者的新宠已经有很长一段时间了,用过RxJava的人,都觉得这个东西简单好用,没用过的小伙伴第一次看到RxJava的代码时可能会觉得这个东西非常繁琐,那么今天,我想通过几个简单的非HelloWorld的案例来让大家彻底理解RxJava的使用。

先来看看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

RxAndroid结合Retrofit,看看谁才是最佳拍档!的更多相关文章

  1. Android RxJava/RxAndroid结合Retrofit使用

    概述 RxJava是一个在 Java VM 上使用可观測的序列来组成异步的.基于事件的程序的库.更重要的是:使用RxJava在代码逻辑上会非常简洁明了,尤其是在复杂的逻辑上.告别迷之缩进. RxAnd ...

  2. 浅谈 RxAndroid + Retrofit + Databinding

    http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0131/3930.html 最近 RxAndroid .MVP.MVVM 一直是 And ...

  3. RxJava + Retrofit完成网络请求

    1.前言 本文基于RxJava.Retrofit的使用,若是对RxJava或Retrofit还不了解的简友可以先了解RxJava.Retrofit的用法再来看这篇文章. 在这片文章之前分别单独介绍过R ...

  4. Retrofit 2.0:有史以来最大的改进

    因为其简单与出色的性能,Retrofit 是安卓上最流行的HTTP Client库之一. 不过它的缺点是在Retrofit 1.x中没有直接取消正在进行中任务的方法.如果你想做这件事必须手动杀死,而这 ...

  5. RxJava+Retrofit+MVP构建的App——聚合资讯

    RtfRxMVP 聚合资讯APP,提供热点资讯,天气预报以及笑话精选服务,使用 Retrofit + RxJava + MVP 构建代码. Hello U 这是我的一个练习项目,第一次尝试运用 MVP ...

  6. retrofit+RXjava二次封装

    接入说明:项目中已集成RXjava,RXandroid.Retrofit,为避免包冲突,不须要再次接入. 就可以直接使用RXjava,Retrofit的所有api. github地址:https:// ...

  7. Rxjava+retrofit+mvp整合

    转载请标明出处: http://blog.csdn.net/forezp/article/details/52621898 本文出自方志朋的博客 最近在看Rxjava,写了一个简单的 demo整合了R ...

  8. 一个响应式数据库框架SQLBrite,完美解决数据库和UI的同步更新!

    相信小伙伴们在开发中或多或少都可能遇到过这样的问题:打开一个应用后,为了快速响应,先将数据库中的数据呈现给用户,然后再去网络上请求数据,请求成功之后将数据缓存至数据库,同时更新UI,但是我们经常会这样 ...

  9. Android实现文章+评论(MVP,RxJava,Dagger2,ButterKnife)

    简介 这个项目主要有两个功能,一个加载网页/文章,另一个用来显示评论.并应用了MVP模式,Dagger2.RxJava.ButterKnife等开源框架.效果图如下: 结构 首先来看一下布局文件: & ...

随机推荐

  1. c while 循环

    c代码: #include <stdio.h> int main(void){ unsigned long sum=1UL; unsigned int j=1U; unsigned ; p ...

  2. 【HDOJ】3957 Street Fighter

    一定要注意审题啊,题目说的是选出做少的英雄打败其余处在任何模式下的英雄.共有Sigma(num of model)个方案,每个方案有Sigma(num of model)+n个决策.挺不错的一道精确覆 ...

  3. AOP 实现的原理简析

    AOP简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能 ...

  4. C# 6和 VB 12的最新特性列表

    随着下个版本的C#发布日逐渐临近,那些还没有完成的特性必须被砍掉.最近从特性列表中被砍掉的特性包括主要构造函数(primary constructor)和声明表达式(declaration expre ...

  5. [HDU 1963] Investment

    Investment Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu   Descrip ...

  6. 【转】Android source build/envsetup.sh学习笔记

    原文网址:http://blog.csdn.net/mliubing2532/article/details/7567164 如果你只需要修改某一个模块的内容,但是却每次都要执行make, 最后等待很 ...

  7. Sharepoint 2010 根据用户权限隐藏Ribbon菜单

    转:http://xiangzhangjun2006.blog.163.com/blog/static/44140966201211715416178/   1.使用SPD打开站点,并打开母版页.默认 ...

  8. 对ASP.NET程序员非常有用的85个工具

    介绍 这篇文章列出了针对 ASP.NET 开发人员的有用工具. 工具 1. Visual Studio Visual Studio Productivity Power tool:Visual Stu ...

  9. mongodb创建数据库和配置用户

    上一篇我们说了mongodb远程连接配置,今天给大家说下mongodb怎么创建数据库和配置用户,毕竟光有远程连接是不够的,我们还要上去操作和放数据的.   系统:centos 5.x   环境:mon ...

  10. 【VLFeat】使用matlab版本计算HOG

    下载 vlfeat-0.9.18    http://www.vlfeat.org cd D:\program\vlfeat-0.9.18\toolbox