-
-
Save flyer88/5d7129fc2ca9010ff6109a81157fbafa to your computer and use it in GitHub Desktop.
| public interface Api{ | |
| void queryPhoto(String query,QueryCallback QueryCallback); | |
| interface QueryCallback{ | |
| void onQuerySuccess(List<Photo> photoList); | |
| void onQueryFailed(Exception e); | |
| } | |
| } |
| public class PhotoUtils{ | |
| Api mApi; | |
| public void handlePhotoSync(){ | |
| mApi.queryPhoto("flyer", new Api.QueryCallback() { | |
| @Override | |
| public void onQuerySuccess(List<Photo> photoList) { | |
| Photo photo = getBestPhoto(photoList); | |
| String imgUrl = photo.getUrl(); | |
| } | |
| @Override | |
| public void onQueryFailed(Exception e) { | |
| ToastUtils.show(e); | |
| } | |
| }); | |
| } | |
| } |
3. map 方法返还值
接下来考虑返回值,首先 map 方法返回的是一个 RxJob对象
其次,因为当前任务已经执行完了,而下一个任务需要当前任务执行后处理的返回值,即func.call(t) 返回的 mapped 值
如果返回的是原有的 RxJob 那么每次调用 map 方法时执行的代码永远是 this.doJob 因此每次执行的内容都是第一个任务了
应用到此处就是 queryPhotoJob.doJob(..)。
因此 map 方法返回的值应该是一个新创建的 RxJob 对象,并且该对象的 doJob 方法会先运行当前任务的 doJob 方法
代码如下:
public RxJob map(Func<T,R> func){
RxJob curJob = this;
return new RxJob() {
@Override
public void doJob(final RxCallback rxCallback) {
curJob.doJob(new RxCallback<T>() {
@Override
public void onNext(T t) {
R mapped = func.call(t);
...
}
@Override
public void onError(Exception e) {
...
}
});
}
};
};把当前例子的泛型值带入如下:
public RxJob map(Func<List<Photo>,R> func){
RxJob queryPhotoJob = this;
RxJob mapJob = new RxJob() {
@Override
public void doJob(final RxCallback rxCallback) {
queryPhotoJob.doJob(new RxCallback<List<Photo>>() {
@Override
public void onNext(List<Photo> photoList) {
R mapped = func.call(photoList);
...
}
@Override
public void onError(Exception e) {
...
}
});
}
};
return mapJob;
};4. func.call() 的返还值传递
考虑如何把 func.call() 调用后的返回的数据往下一个 RxJob 传递
直接调用下一个 RxJob 中回调的 rxCallback.onNext()方法即可,对于错误也同样调用 rxCallback.onError(e) 即可。
public RxJob map(Func<T,R> func){
RxJob curJob = this;
return new RxJob() {
@Override
public void doJob(final RxCallback rxCallback) {
curJob.doJob(new RxCallback<T>() {
@Override
public void onNext(T t) {
R mapped = func.call(t);
rxCallback.onNext(t);
}
@Override
public void onError(Exception e) {
rxCallback.onError(e);
}
});
}
};
}代入当前例子:
public RxJob map(Func<List<Photo>,R> func){
RxJob<List<Photo>> queryPhotoJob = this;
RxJob mapJob = new RxJob() {
@Override
public void doJob(final RxCallback mapJobCallback) {
queryPhotoJob.doJob(new RxCallback<List<Photo>>() {
@Override
public void onNext(List<Photo> photoList) {
R mapped = func.call(photoList);
mapJobCallback.onNext(mapped);
}
@Override
public void onError(Exception e) {
mapJobCallback.onError(e);
}
});
}
};
return mapJob;
}最终只需要确定泛型参数类型 R,他的作用是确定下一个RxJob 对象的泛型值
R 由 func.call() 方法 确定,也就是之前说的,在具体的 map 方法被调用时,参数的泛型值是可以确定的
Func 函数负责把 T —> R 转换,因此,最终的 map 方法如下:
public <R> RxJob<R> map(Func<T,R> func){
RxJob curJob = this;
return new RxJob<R>() {
@Override
public void doJob(final RxCallback<R> rxCallback) {
curJob.doJob(new RxCallback<T>() {
@Override
public void onNext(T t) {
R mapped = func.call(t);
rxCallback.onNext(mapped);
}
@Override
public void onError(Exception e) {
rxCallback.onError(e);
}
});
}
};
}应用到当前例子,带入泛型值如下
public<Photo> RxJob<Photo> map(Func<List<Photo>,Photo> func){
RxJob<List<Photo>> queryPhotoJob = this;
RxJob<Photo> mapJob = new RxJob<Photo>() {
@Override
public void doJob(final RxCallback<Photo> mapJobCallback) {
queryPhotoJob.doJob(new RxCallback<List<Photo>>() {
@Override
public void onNext(List<Photo> photoList) {
Photo mapped = func.call(photoList);
mapJobCallback.onNext(mapped);
}
@Override
public void onError(Exception e) {
mapJobCallback.onError(e);
}
});
}
};
return mapJob;
}整个任务如何运行
RxJob<List<Photo>> queryPhotoJob = new RxJob<List<Photo>>(){
@Override
public void doJob(final RxCallback<List<Photo>> rxCallback) {
mApi.queryPhoto("flyer", new Api.QueryCallback() {
@Override
public void onQuerySuccess(List<Photo> photoList) {
rxCallback.onNext(photoList);
}
@Override
public void onQueryFailed(Exception e) {
rxCallback.onError(e);
}
});
}
};
};
RxJob<Photo> bestPhotoJob = queryPhotoJob.map(photoList -> { return getBestPhoto(photoList);})
RxJob<String> urlJob = .map(photo -> {return photo.getUrl();})
urlJob.doJob(new RxCallback<String>() {
@Override
public void onNext(String s) {
ToastUtils.show(s);
}
@Override
public void onError(Exception e) {
...
}
});解释代码,第一个 map 方法 返还了一个 RxJob<Photo> 对象,第二个 map 返还了一个 RxJob<String> 对象,第三个 doJob 方法触发整个任务
doJob 方法触发的第一个方法是 urlJob 中的 doJob 方法,由于 urlJob 对象是由 map 方法创建的
因此,在执行 ToastUtils.show(s) 方法之前,会先执行 bestPhotoJob.doJob()
同样,queryPhotoJob.doJob()也会执行在 bestPhotoJob.doJob() 方法之前
因此整体过程就是 queryPhotoJob.doJob() —> bestPhotoJob.doJob() —> urlJob.doJob()
而这执行过程中,R mapped = func.call(T) 会先被调用,因此单个 RxJob 调用链如下:
在调用每个
RxJob.onNex()情况下(即成功的情况下,没有出错)
queryPhotoJob.doJob() : mApi.query —> func.call(t) —> getBestPhoto(photoList)
bestPhotoJob.doJob() : func.call(t) —> photo.getUrl()
urlJob.doJob(): ToastUtil.show()
比较炫酷的写法如下:
RxJob<List<Photo>> queryPhotoJob = new RxJob<List<Photo>>(){
@Override
public void doJob(final RxCallback<List<Photo>> rxCallback) {
mApi.queryPhoto("flyer", new Api.QueryCallback() {
@Override
public void onQuerySuccess(List<Photo> photoList) {
rxCallback.onNext(photoList);
}
@Override
public void onQueryFailed(Exception e) {
rxCallback.onError(e);
}
});
}
};
};
queryPhotoJob
.map(photoList -> { return getBestPhoto(photoList);})
.map(photo -> {return photo.getUrl()})
.doJob(...);
2.
doJob方法的调用然后考虑里面具体的调用逻辑,首先考虑任务调用,第一个
map方法在触发的时候,queryPhotoJob本身已经是一个RxJob对象了它的实现内容也简单,在创建包裹类时已经有解释了。
也就是说,如果我要调用
map方法触发传入的func匿名内部类,就必须先调用queryPhotoJob.doJob(..)于是把代码变成
应用到上述例子中其具体的泛型值变化就成了如下代码
此时需要考虑的就是在哪里调用
func函数,它是负责把T —> R,因此该部分代码必然是在当前任务执行完后,拿到当前任务的回调值,然后进行转换,即
map方法会变成如下