RxJava 之前奏:原理分析
前言:RxJava在国内越来越火,本文只是原理分析的总结。代码不多,但有些绕,一步一步的推进,对于理解RxJava来说还是十分有好处的。但确实需要很大的毅力去坚持下去看完。
首先我们进入一个例子,关于猫的例子。
我们有个 Web API,能根据给定的查询请求搜索到整个互联网上猫的图片。每个图片包含可爱指数的参数(描述图片可爱度的整型值)。我们的任务将会下载到一个猫列表的集合,选择最可爱的那个,然后把它保存到本地。
首先定义实体类
public class Cat implements Comparable<Cat> {
/**
* 图片
*/
String image;
/**
* 喜爱度
*/
int cuteness;
@Override
public int compareTo(Cat another) {
return Integer.compare(cuteness, another.cuteness);
}
}
定义一个Uri类,用来定义图片保存的地址
public class Uri {
}
定义Api接口类,主要查询猫和保存猫的方法。
public interface Api {
/**
* 查询所有猫
* @param query
* @return
*/
List<Cat> queryCats(String query);
/**
* 保存
* @param cat
* @return
*/
Uri store(Cat cat);
}
定义业务类CastsHelp
public class CastsHelp {
Api api;
//保存猫
public Uri saveTheCutestCat(String query) {
List<Cat> queryCats = api.queryCats(query);
Cat cat = findCustest(queryCats);
Uri savedUri = api.store(cat);
return savedUri;
}
//查询最受喜爱的猫
private Cat findCustest(List<Cat> queryCats) {
return Collections.max(queryCats);
}
}
ok,我们的第一个例子写完了,让我们回过头来再仔细看一下这个例子,该业务逻辑类CastsHelp,里面包含了两个方法,其中saveTheCutestCat方法里面,包含了三个组合的方法,最终获取到保存猫的地址,并返回。这种组合方式即简单,又直白。一眼看去,清晰,明了。但我们往下看。
异步执行
我们知道,对于一些网络请求,我们通常都需要进行异步去执行,那么,对于刚才说saveTheCutestCat方法,我们就不能如此写,对于api的中的方法,我们需要利用接口回调的方式回传结果。于是我们修改我们的代码。
public interface Api {
interface CatsQueryCallback{
void onCatListReceived(List<Cat> cats);
void onCatsQueryError(Exception e);
}
interface StoreCallback{
void onCateStored(Uri uri);
void onStoteFailed(Exception e);
}
/**
* 查询所有猫
* @param query
* @return
*/
List<Cat> queryCats(String query,CatsQueryCallback castQueryCallback);
/**
* 保存
* @param cat
* @return
*/
Uri store(Cat cat,StoreCallback storeCallback);
}
修改了一下api中的方法,因为对于猫和保存猫,分别为网络请求,和I/O操作,我们不能进行同步操纵,所以添加了两个接口,分别查询猫的和保存猫地址的结果的回调。
同时我们需要修改一下我们的业务逻辑类CastsHelp,也需要添加接口回调。
public interface CutestCatCallback{
void onCutestCatSaved(Uri uri);
void onCutestCatFail(Exception e);
}
Api api;
public void saveTheCutestCat(String query,final CutestCatCallback custestCatCallback) {
List<Cat> queryCats = api.queryCats(query,new CatsQueryCallback() {
@Override
public void onCatsQueryError(Exception e) {
//查询猫失败
custestCatCallback.onCutestCatFail(e);
}
@Override
public void onCatListReceived(List<Cat> cats) {
Cat cat = findCustest(cats);
api.store(cat, new StoreCallback() {
@Override
public void onStoteFailed(Exception e) {
//保存猫失败
custestCatCallback.onCutestCatFail(e);
}
@Override
public void onCateStored(Uri uri) {
custestCatCallback.onCutestCatSaved(uri);
}
});
}
});
}
private Cat findCustest(List<Cat> queryCats) {
return Collections.max(queryCats);
}
代码开始复杂了,我们再来分析一下代码,在CastsHelp的saveTheCutestCat方法,我们传入了一个url,以及结果的回调,及该方法调用者用来实现的接口回调。
- 首先,调用api的queryCats方法查询所有的猫,因为该方法是异步的,所以我们传入一个接口的实现类,该接口包含了两个回调方法,onCatsQueryError()查询失败的方法,在此方法中,我们直接调用调用者实现的接口告诉调用者获取信息出现异常,onCatListReceived(List cats)方法,表明查询猫成功,并返回猫列表。
- 我们在onCatListReceived(List cats)方法内,此时查询猫列表的数据已经返回,我们继续调用了获取最喜爱的猫方法findCustest,然后保存猫。store()方法又包含了两个回调方法,在onStoteFailed()方法中,依然如上。在成功的方法onCateStored()中,我们将获取到的值通过调用者的实现接口进行回传给调用者。
好了,我们完成了异步任务的处理,代码复杂度大大的提升了,而且对于这么多接口回调,看着都心理难受。
接口回调的封装
我们加入异步任务之后,整个程序在逻辑