Skip to content

Instantly share code, notes, and snippets.

@flyer88
Last active March 8, 2022 03:44
Show Gist options
  • Save flyer88/5d7129fc2ca9010ff6109a81157fbafa to your computer and use it in GitHub Desktop.
Save flyer88/5d7129fc2ca9010ff6109a81157fbafa to your computer and use it in GitHub Desktop.
如何实现 RxJava 的链式调用 -- map 方法的实现
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);
}
});
}
}
@flyer88
Copy link
Author

flyer88 commented May 24, 2017

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 对象的泛型值

Rfunc.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;
}

@flyer88
Copy link
Author

flyer88 commented May 24, 2017

整个任务如何运行

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(...);

@flyer88
Copy link
Author

flyer88 commented May 24, 2017

=================================

异步里面还有异步方法,flatMap 待续

=================================

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment