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)会产生异常!
{"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);
}
其中basebean
public 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);
}
}
});
其中BjxListBean
public 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;
}
}
}