Android网络请求框架之Retrofit(二)
2016-03-08 14:54
627 查看
前面一篇文章介绍了Retrofit的基本用法,没有看过的童鞋可以移步:Android网络请求框架之Retrofit(一),现在我们来继续介绍Retrofit配合RxJava、RxAndroid的用法。
配合Rx是为了体现函数式编程的思想,其实用法差别不大,只是在接口里定义方法的返回值有所差别,当然,build.gradle文件里需要导入两个库地址
下面我们以更新任务为例,观察两种方式的区别
方法很容易区别,一个是返回参数在回调接口里,一个是直接返回,但返回的不是最终的对象。
按照常规的调用
这种调用没什么好说的,和前面一篇文章里的一样,服务器返回的结果会封装在RCallback里面,并且回调方法在主线程。
下面我们看看按照Rx模式调用之一
在这里,接口定义的方法直接返回了一个Observable对象,指定这个对象发生订阅的线程,然后订阅事件,最后也是异步回调的,不过在这个过程中,我们可以指定回调方法发生的线程,看起来的话onNext方法和success方法其实没啥区别,都带回了我们需要的数据,但是从代码层次上来看,Rx模式的代码逻辑层次更清楚。
下面我们再看看按照Rx模式调用之二
这里是反回了一个Call对象,调用enqueue的时候就像我们常规模式调用时那样传入callback接口,从里面获取数据。
当然RX模式的好处远不止这一个,比如说,当我们需要显示等待dialog的时候,常规的异步式调用可能就需要我们维护一个progressdialog,但Rx模式就可以很方便的实现。Subscriber有一个空实现的方法onStart,是在开始连接服务器之前调用的,我们可以封装一个commonSubscriber,在 onStart方法里去显示一个progressdialog,在onError或onComplete方法里去自动销毁这个progressdialog。
关于Rx相关的知识,我也知道得很有限,有一些比较专业的用法我也不敢信笔涂鸦,有兴趣的小伙伴可以去查阅一下相关的资料,或许就会有更大的发现。比如说可以指定多次observeOn,但是subscribeOn只认可第一次;可以用filter方法过滤调一些返回值,可以用flatMap封装下一步需要的参数等等。
最后我贴出一段我用纯Rx模式实现的请求代码供大家参考
配合Rx是为了体现函数式编程的思想,其实用法差别不大,只是在接口里定义方法的返回值有所差别,当然,build.gradle文件里需要导入两个库地址
io.reactivex:rxjava:1.0.14 io.reactivex:rxandroid:1.0.1
下面我们以更新任务为例,观察两种方式的区别
public interface ITask { //RX模式的方法定义之一 @PUT("/task/{Id}") Observable<Task> update(@Path("Id") String Id,@Body HashMap<String, Object> body); //RX模式的方法定义之二 @PUT("/task/{Id}") Call<Task> _update(@Path("Id") String Id,@Body HashMap<String, Object> body); //常规异步式的方法定义 @PUT("/task/{Id}") void update_(@Path("Id") String Id,@Body HashMap<String, Object> body,Callback<Task> callback); }
方法很容易区别,一个是返回参数在回调接口里,一个是直接返回,但返回的不是最终的对象。
按照常规的调用
HashMap<String, Object> map = new HashMap<>(); map.put("title", title); map.put("content", content); map.put("responsiblePersons", Arrays.asList(new Reviewer(mTask.getResponsiblePerson()))); map.put("members", mTask.getMembers()); map.put("actualendAt", mTask.getActualEndAt()); map.put("remindflag", mTask.getRemindTime() > 0); map.put("remindtime", mTask.getRemindTime()); map.put("reworkflag", switch_approve.isChecked()); if (!TextUtils.isEmpty(mTask.getAttachmentUUId()) && mTask.getAttachments().size() > 0) { map.put("attachmentUUId", mTask.getAttachmentUUId()); } if (!TextUtils.isEmpty(mTask.getProjectId())) { map.put("projectId", mTask.getProjectId()); } RestAdapterFactory.getInstance().build(Config_project.API_URL()).create(ITask.class).update_(mTask.getId(), map,new RCallback<Task> (){ @overide public void success(Task task,Response r){ task.setAck(true); Toast(getString(R.string.app_add) + getString(R.string.app_succeed)); Intent intent = new Intent(); intent.putExtra("data", task); setResult(Activity.RESULT_OK, intent); onBackPressed(); } @Overide public void failure(RetrofitError e){ } });
这种调用没什么好说的,和前面一篇文章里的一样,服务器返回的结果会封装在RCallback里面,并且回调方法在主线程。
下面我们看看按照Rx模式调用之一
HashMap<String, Object> map = new HashMap<>(); map.put("title", title); map.put("content", content); map.put("responsiblePersons", Arrays.asList(new Reviewer(mTask.getResponsiblePerson()))); map.put("members", mTask.getMembers()); map.put("actualendAt", mTask.getActualEndAt()); map.put("remindflag", mTask.getRemindTime() > 0); map.put("remindtime", mTask.getRemindTime()); map.put("reworkflag", switch_approve.isChecked()); if (!TextUtils.isEmpty(mTask.getAttachmentUUId()) && mTask.getAttachments().size() > 0) { map.put("attachmentUUId", mTask.getAttachmentUUId()); } if (!TextUtils.isEmpty(mTask.getProjectId())) { map.put("projectId", mTask.getProjectId()); } RestAdapterFactory.getInstance().build(Config_project.API_URL()).create(ITask.class).update(mTask.getId(), map) .observeOn(AndroidSchedulers.mainThread())//指定订阅的线程-主线程 .subscribe(new Subscriber<Task>() {//订阅 //处理完成 @Override public void onCompleted() { } //处理出错 @Override public void onError(Throwable e) { e.printStackTrace(); } //处理过程 @Override public void onNext(Task task) { task.setAck(true); Toast(getString(R.string.app_add)+getString(R.string.app_succeed)); Intent intent = new Intent(); intent.putExtra("data", task); setResult(Activity.RESULT_OK, intent); onBackPressed(); } });
在这里,接口定义的方法直接返回了一个Observable对象,指定这个对象发生订阅的线程,然后订阅事件,最后也是异步回调的,不过在这个过程中,我们可以指定回调方法发生的线程,看起来的话onNext方法和success方法其实没啥区别,都带回了我们需要的数据,但是从代码层次上来看,Rx模式的代码逻辑层次更清楚。
下面我们再看看按照Rx模式调用之二
HashMap<String, Object> map = new HashMap<>(); map.put("title", title); map.put("content", content); map.put("responsiblePersons", Arrays.asList(new Reviewer(mTask.getResponsiblePerson()))); map.put("members", mTask.getMembers()); map.put("actualendAt", mTask.getActualEndAt()); map.put("remindflag", mTask.getRemindTime() > 0); map.put("remindtime", mTask.getRemindTime()); map.put("reworkflag", switch_approve.isChecked()); if (!TextUtils.isEmpty(mTask.getAttachmentUUId()) && mTask.getAttachments().size() > 0) { map.put("attachmentUUId", mTask.getAttachmentUUId()); } if (!TextUtils.isEmpty(mTask.getProjectId())) { map.put("projectId", mTask.getProjectId()); } RestAdapterFactory.getInstance().build(Config_project.API_URL()).create(ITask.class)._update(mTask.getId(), map).enqueue(new RCallback<Task>() { @Override public void success(Task task) { task.setAck(true); Toast(getString(R.string.app_add)+getString(R.string.app_succeed)); Intent intent = new Intent(); intent.putExtra("data", task); setResult(Activity.RESULT_OK, intent); onBackPressed(); } @Override public void onFailure(Throwable error) { } });
这里是反回了一个Call对象,调用enqueue的时候就像我们常规模式调用时那样传入callback接口,从里面获取数据。
当然RX模式的好处远不止这一个,比如说,当我们需要显示等待dialog的时候,常规的异步式调用可能就需要我们维护一个progressdialog,但Rx模式就可以很方便的实现。Subscriber有一个空实现的方法onStart,是在开始连接服务器之前调用的,我们可以封装一个commonSubscriber,在 onStart方法里去显示一个progressdialog,在onError或onComplete方法里去自动销毁这个progressdialog。
public abstract class CommonSubscriber extends Subscriber<Serializable> { private CustomProgressDialog dialog; public CommonSubscriber(Activity context) { dialog = new CustomProgressDialog(context); } @Override public void onStart() { super.onStart(); dialog.show(); } @Override public void onNext(Serializable serializable) { BaseBen baseBen = (BaseBen) serializable; if(null!=baseBen) { if ((!TextUtils.isEmpty(baseBen.getErrorCode())&&baseBen.getErrorCode().contains( ErrorUtil.ERROR_TOKEN_ERROR)) || ((!(baseBen instanceof TokenInfo)) && null == BusApplication.getInstance().getTokenInfo())) { BusApplication.getInstance().backToLogin(); } } } @Override public void onError(Throwable e) { dialog.dismiss(); dialog=null; } @Override public void onCompleted() { dialog.dismiss(); dialog=null; } }
关于Rx相关的知识,我也知道得很有限,有一些比较专业的用法我也不敢信笔涂鸦,有兴趣的小伙伴可以去查阅一下相关的资料,或许就会有更大的发现。比如说可以指定多次observeOn,但是subscribeOn只认可第一次;可以用filter方法过滤调一些返回值,可以用flatMap封装下一步需要的参数等等。
最后我贴出一段我用纯Rx模式实现的请求代码供大家参考
//-------------------------------RxJava实现方式开始-------------------------------- Observable.just(schedule) .subscribeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) //判断行程是否有效,过滤掉无效行程 .filter(new Func1<TourSchedule, Boolean>() { @Override public Boolean call(TourSchedule tourSchedule) { if (null == schedule) { ptrFrameLayout.refreshComplete(); dialog.dismiss(); ToolToast.showShort("车次信息错误,无法获取订单"); } return null != schedule; } }) //网络请求置于IO线程 .observeOn(Schedulers.io()) //先去请求服务器数据 .flatMap(new Func1<TourSchedule, Observable<CommonListBen<TravelOrderForm>>>() { @Override public Observable<CommonListBen<TravelOrderForm>> call(TourSchedule schedule) { HashMap<String, Object> map = new HashMap<>(); map.put("busNoId", schedule.getBusNoId()); map.put("busId", schedule.getBusId()); map.put("day", schedule.getDay()); map.put("planId", schedule.getPlanId()); return ServiceGenerator.getInstance().create(IOrderForm.class, BusApplication.getInstance().getToken()).getOrderFormList_(map); } }) //截获错误,不回调onError方法,使流程继续 .onErrorReturn(new Func1<Throwable, CommonListBen<TravelOrderForm>>() { @Override public CommonListBen<TravelOrderForm> call(Throwable throwable) { return null; } }) .observeOn(Schedulers.newThread()) //请求的结果转换为最终需要的数据 .map(new Func1<CommonListBen<TravelOrderForm>, ArrayList<TravelOrderForm>>() { @Override public ArrayList<TravelOrderForm> call(CommonListBen<TravelOrderForm> travelOrderFormCommonListBen) { return null == travelOrderFormCommonListBen ? null : travelOrderFormCommonListBen.getData(); } }) //处理服务器返回的数据,混合缓存 .flatMap(new Func1<ArrayList<TravelOrderForm>, Observable<ArrayList<TravelOrderForm>>>() { @Override public Observable<ArrayList<TravelOrderForm>> call(ArrayList<TravelOrderForm> travelOrderForms) { if (mDao == null) mDao = new TravleOrderFormDao(mContext); //从数据库获取 if (null == travelOrderForms) { //需要取存数据,以planId为主键 TravelOrderFormData dataDb = mDao.get(schedule.getPlanId()); if (null != dataDb) { Gson gson = new Gson(); Type type = new TypeToken<ArrayList<TravelOrderForm>>() { }.getType(); travelOrderForms = gson.fromJson(dataDb.getJson(), type); } } //存数据库 else { TravelOrderFormData data = new TravelOrderFormData(); data.setPlanId(schedule.getPlanId()); Gson gson = new Gson(); data.setJson(gson.toJson(travelOrderForms)); mDao.add(data); } return Observable.just(travelOrderForms); } }) //显示最后获得的结果 .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<ArrayList<TravelOrderForm>>() { @Override public void onCompleted() { dialog.dismiss(); ptrFrameLayout.refreshComplete(); } @Override public void onError(Throwable e) { dialog.dismiss(); ptrFrameLayout.refreshComplete(); } @Override public void onNext(ArrayList<TravelOrderForm> datas) { travelOrderForms = datas; handleCustomers(); dataChange(); } }); //-------------------------------RxJava实现方式结束--------------------------------
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件