Rxjava+retrofit 添加公共请求参数及请求结果封装
RxJava + Retrofit + okHttp 做为当前android主流的网络请求框架,写一些自己在项目中的应用!本文主要内容:1.为所用请求添加公共的请求参数。2.封装适合于自己项目的服务器接口数据处理类。
开发环境
retrofitVersion = ‘2.2.0’
ok3Version = ‘3.6.0’
rxjavaVersion = ‘1.2.7’
rxAndroidVersion = ‘1.2.1’
rxlifecycleVersion = ‘0.3.0’
其中,rxlifecycleVersion是为了防止RxJava中subscription导致内存泄漏而诞生的。例如:当要引用的view(fragment,activity)被销毁,但rxjava生命周期未结束时,再次调用已销毁的view(fragment,activity)会产生异常!
- 形如一个Post接口:http://base/interface/xxx
要求每个接口都有一个必传字段:APPTOKEN(记录用户登陆状态)
返回值可能为:
{"erron":"100000","msg":"成功"}//接口返回单纯消息{"data":{},"erron":"100000","msg":"成功"}//接口返回带有详细字段{"nowPage":"1","totalPage":"4","data":[],"erron":"100000","msg":"成功"}//接口返回分页数据
首先为所有请求都加一个默认的apptoken字段。使用到一个Okhttp3的网络拦截器Interceptor。
核心代码:
builder = new OkHttpClient.Builder(); if (BuildConfig.DEBUG) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); builder.addInterceptor(logging); } builder.connectTimeout(6 * 1000, TimeUnit.MILLISECONDS)//10s连接超时 .readTimeout(10 * 1000, TimeUnit.MILLISECONDS) .writeTimeout(10 * 1000, TimeUnit.MILLISECONDS); //添加token拦截器 builder.addInterceptor(new TokenInterceptord()); //添加网络异常拦截器 Interceptor netErrorInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { if (NetWorkUtil.isNetworkConnected()) return chain.proceed(chain.request()); else { String res = "{\"erron\":\"-1200\",\"msg\":\"网络连接失败\",\"nowPage\":\"0\",\"totalPage\":\"0\"}"; Response response = new Response.Builder() .code(200) .request(chain.request()) .protocol(Protocol.HTTP_1_1) .addHeader("Cache-Control", "no-cache") .addHeader("Content-Type", "text/html; charset=utf-8") .body(RealResponseBody.create(MediaType.parse("text"), res.getBytes("utf-8"))) .build(); return response; } } }; builder.addNetworkInterceptor(netErrorInterceptor);
上文中添加了两个网络拦截器,其中添加apptoken的拦截器是应用拦截器(Application Intercetor),添加网络异常的拦截器是网络拦截器(netErrorInterceptor)。
添加网络异常的拦截器主要作用是为了后续结果集封装的时候不需要额外处理网络异常的情况。
apptoken参数添加拦截器的详细实现:
public class TokenInterceptord implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request.Builder requestBuilder = request.newBuilder(); if (canInjectIntoBody(request)) { FormBody.Builder formBodyBuilder = new FormBody.Builder(); formBodyBuilder.add("apptoken", SharedPreUtil.getAppToken());//此处添加apptoken参数 RequestBody formBody = formBodyBuilder.build(); String postBodyString = bodyToString(request.body()); postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody); requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString)); } request=requestBuilder.build(); return chain.proceed(request); } private boolean canInjectIntoBody(Request request) { if (request == null) { return false; } if (!TextUtils.equals(request.method(), "POST")) { return false; } RequestBody body = request.body(); if (body == null) { return false; } MediaType mediaType = body.contentType(); if (mediaType == null) { return false; } if (!TextUtils.equals(mediaType.subtype(), "x-www-form-urlencoded")) { return false; } return true; } private String bodyToString(final RequestBody request) { try { final RequestBody copy = request; final Buffer buffer = new Buffer(); if (copy != null) copy.writeTo(buffer); else return ""; return buffer.readUtf8(); } catch (final IOException e) { return "did not work"; } }}
其实就是拦截request请求并添加了一个apptoken的post字段。
* 接下来分析3种返回类型,一般app接口应该差不多就这3种情况。
1. 针对第一种:
{“erron”:”100000”,”msg”:”成功”}//接口返回单纯消息信息
自定义处理结果BaseBeanSubscribe
public abstract class BaseBeanSubscribe<T extends BaseBean> extends Subscriber<T> { public enum ERROR_TYPE { DATA_EMPTY,//数据为空 DATA_ERROR,//数据解析错误 NET_ERROR,//网络连接错误 TOKEEN_ERROR,//apptoken无效或异常。 } @Override public void onCompleted() { } @Override public void onError(Throwable e) { LogUtils.i("Zuzu", "ResultSubscriber-->exception"); e.printStackTrace(); if (NetWorkUtil.isNetworkConnected()) { onError(ERROR_TYPE.DATA_ERROR, "未知异常!"); } else { onError(ERROR_TYPE.NET_ERROR, "网络连接超时,请检测您的网络状况!"); } LogUtils.i("Zuzu", "request fail!"); } @Override public void onNext(T t) { if (t == null) { LogUtils.i("Zuzu", "data_empty!"); onError(ERROR_TYPE.DATA_EMPTY, "服务器异常!"); } else if ("100002".equals(t.getErron()) || "100003".equals(t.getErron())) { String msg; if ("-1".equals(SharedPreUtil.getAppToken())) { msg = "您还没有登录,不能进行该操作!"; } else { msg = "抱歉您账户已过期,请重新登录!"; } onError(ERROR_TYPE.TOKEEN_ERROR, msg); } else if ("100000".equals(t.getErron())) { sucess(); } else if ("-1200".equals(t.getErron())) { onError(ERROR_TYPE.NET_ERROR, t.getMsg()); } else { onError(ERROR_TYPE.DATA_ERROR, t.getMsg()); } } //请求成功 protected abstract void sucess(); //发生错误! protected abstract void onError(ERROR_TYPE type, String msg);}其中basebeanpublic class BaseBean<T> { private String erron; private String msg; private T data; ...set get方法...}
该代码段实现了根据结果过滤集处理错误的情况。由于上文已经处理过了网络异常情况,因此此处可以直接获取网络异常情况。
2 . 第二种:
{“data”:{},”erron”:”100000”,”msg”:”成功”}//接口返回带有详细字段
public abstract class ResultSubscriber<D, T extends BaseBean<D>> extends BaseBeanSubscribe<T> { @Override public void onNext(T t) { if (t != null && "100000".equals(t.getErron())) { onSuccess(t.getData()); return; } super.onNext(t); } @Override protected void sucess() { } //请求成功 protected abstract void onSuccess(D data);}
这样写的好处是onSuccess中返回的数据是”data”:{}的数据。
3. 最后一种类型,分页:
{“nowPage”:”1”,”totalPage”:”4”,”data”:[],”erron”:”100000”,”msg”:”成功”}
public abstract class PageListResultSubscriber<D, T extends BasePageBean<D>> extends ResultSubscriber<List<D>, T> { @Override public void onNext(T t) { if (t != null && "100000".equals(t.getErron())) { onSuccess(t.getData(), Integer.parseInt(t.getNowPage()), Integer.parseInt(t.getTotalPage())); return; } super.onNext(t); } protected abstract void onSuccess(List data, int nowPage, int totalPage); @Override protected void onSuccess(List data) { //空实现 }
onSucess中返回List集合,以及totalpage,及nowpage
* 最后完成上述准备工作,代码中的使用就简单多了
eg:有一个接口
@POST(“admin/index/surnames”)
@FormUrlEncoded
Observable getBjxList(@Field(“id”) String id);
mService.getBjxList("0") .compose(getView().bindToLifecycle()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new ResultSubscriber,BjxListBean>() { @Override protected void onSuccess(List data) { if(getView()!=null) { getView().showSucessUi(data); } } @Override protected void onError(ERROR_TYPE type, String msg) { if(getView()!=null) { getView().showError(type,msg); } } });其中BjxListBeanpublic class BjxListBean extends BaseBean<List<BjxListBean.DataBean>> { public static class DataBean implements Serializable{ private String id; private String xing; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getXing() { return xing; } public void setXing(String xing) { this.xing = xing; } }}
更多相关文章
- Android8.1 Launcher3 去掉抽屉(一)
- cocos2d-x添加广告条(IOS and Android)
- Android(安卓)自定义TextView实现宫格布局,Drawable添加图片并控
- Android(安卓)两个Fragment之间传递数据实例详解
- android ListView添加事件并获取选中项的值
- Android(安卓)7.0、8.1 导航栏上添加图标 及 相应功能
- Android(安卓)UI设计:GridView
- SQLite数据库浅谈
- 【Android】使用persist属性来调用脚本文件