MvpRoute 封装了Retrofit 和RxJava结合的网络请求
内置了 错误处理 自动刷新token cookie持久化操作
正常的后台服务器返回数据都会遵循一定的格式
{ "errorCode":0, "data":null, "errorMsg":"error_msg" }如上面 当errorCode 为0的时候 请求成功 data 为返回的数据
其他值的时候请求失败 如token失效 密码错误之类的而客户端 最后只想拿到的数据其实只是data里面的数据 所以MvpRoute专门对这里进行了处理
编写一个类 实现IBaseBean 接口 来个MvpRoute当前请求是否成功 及错误原因
public class BaseData<T> implements IBaseBean<T> {
//这里 服务端的基础返回数据
private int errorCode;
private String errorMsg;
private T data;
//返回客户端只想要的那串 数据
@Override
public T getData() {
return data;
}
//是否请求成功
@Override
public boolean isOk() {
return errorCode==0;
}
//返回错误原因 当请求失败后 Retrofit 会获取此错误码
@Override
public String getErrorMsg() {
return errorMsg;
}
//返回错误码
@Override
public int getStatusCode() {
return errorCode;
}
}编写基础数据结构类 后 客户端生成实体类 只需要生成data里面的数据即可
- 如一个登陆接口返回的数据 我们只需要生成data的实体类即可
{
"data": {
"collectIds": [
1339,
1494,
1533,
1260,
1258,
1255,
96,
94,
203,
2994,
2922,
-1,
-1,
-1,
1165
],
"email": "tttx0307@163.com",
"icon": "",
"id": 428,
"password": "123",
"token": "",
"type": 0,
"username": "tianxiaolong"
},
"errorCode": 0,
"errorMsg": ""
}public class LoginResponse {
/**
* collectIds : [1339,1494,1533,1260,1258,1255,96,94,203,2994,2922,-1,-1,-1,1165]
* email : tttx0307@163.com
* icon :
* id : 428
* password : 123
* token :
* type : 0
* username : tianxiaolong
*/
private String email;
private String icon;
private int id;
private String password;
private String token;
private int type;
private String username;
private List<Integer> collectIds;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<Integer> getCollectIds() {
return collectIds;
}
public void setCollectIds(List<Integer> collectIds) {
this.collectIds = collectIds;
}
@Override
public String toString() {
return "LoginResponse{" +
"email='" + email + '\'' +
", icon='" + icon + '\'' +
", id=" + id +
", password='" + password + '\'' +
", token='" + token + '\'' +
", type=" + type +
", username='" + username + '\'' +
", collectIds=" + collectIds +
'}';
}
}实现 IResponseErrorMsg 接口
public interface IResponseErrorMsg {
String getErrorMsg(int errcode);
}配置服务器的异常信息 如果errorMsg没有返回
public class ErrorResponse implements IResponseErrorMsg {
@Override
public String getErrorMsg(int errcode) {
String msg = "";
switch(errcode){
case -1:
msg= "好像账号不对啊";
default:
}
return msg;
}
}实现 IRefreshToken类
public interface IRefreshToken {
//刷新token网络请求
Observable refreshTokenSuccful();
//是否需要刷新token
boolean isTokenException(int code,String errorMsg);
}实现
public class RefreshToken implements IRefreshToken {
@Override
public synchronized Observable refreshTokenSuccful() {
LoginService api = RetrofitClient.getInstance().createRefreshToken(LoginService.class);
// 如果需要保存信息 调用doOnnext操作符即可
return api.login("tianxiaolong", "123");
}
@Override
public boolean isTokenException(int code, String errorMsg) {
if ("请先登录!".equals(errorMsg)) {
return true;
}
return false;
}
}在 Application中初始化Retrofit
//配置baseUrl
RetrofitConfig config = new RetrofitConfig("http://www.wanandroid.com/");
//配置拦截器
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//配置cokkie持久化
builder.cookieJar(new CookiesManager(this));
//配置异常类
config.setErrorResponse(new ErrorResponse());
//配置刷新token类
config.setiRefreshToken(new RefreshToken());
//配置基础数据结构类 即实现IBaseBean的类
config.setGsonClass(BaseData.class);
//初始化
config.setBuilder(builder);
RetrofitClient.init(config);-
编写网络请求Service
public interface LoginService { @FormUrlEncoded @POST("user/login") Observable<LoginResponse> login(@Field("username") String username, @Field("password") String passworld); @GET("lg/collect/list/{page}/json") Observable<CollectListBean> getCollect(@Path("page") String page); }
-
调用
//获取Service loginService = RetrofitClient.getInstance().createApi(LoginService.class); @Override public void getCollectList(String page,String userNmae,String passwrold) { loginService.getCollect(page) //线程调度 回调到主线程 .compose(new RxScheduer.IO_MAIN<CollectListBean>()) //异常处理 .onErrorResumeNext(new RxScheduer.HandlerException<CollectListBean>()) //这里是在presenter里面请求的 自带rxmanager view .subscribe(new BaseOberver<CollectListBean>(rxManager,view) { @Override public void onNext(CollectListBean collectListBean) { //请求成功 view.showCollectList(collectListBean); } //如果请求失败 会自动回调 BaseActivity的showError方法 }); }
关于 token刷新 内部使用的是动态代理 针对每个service进行动态代理 已经处理了多个请求访问时出现的token失效问题
关于 异常处理 自定义Retrofit解析器 在请求失败时抛出异常
由onErrorResumeNext操作符拦截 并处理 -