本人之前一直用的OkHttp, 最近换成了Retrofit, 然后发现一个后台接口要对应一个interface 这也太麻烦了吧!!
为了偷懒,大概研究了Retrofit用法之后 封装了这么一套万能的Retrofit!
首先是接口数据的bean,一般来说后台的返回格式都是固定的! 如果不是的话 让后台重写!例如下的json格式
/**
* data : {"email":"","expireTime":"1527738202273","status":""}
* errors : []
* reqId :
* retCode : 2
* retMsg : 参数异常
* sessionId : null
*/
data部分为真实的返回部分,剩下的是一些固定的返回 根据返回数据 写一个BaseBean
public class BaseBean<T> implements Serializable {
private T data;
private String reqId;
private int retCode;
private String retMsg;
private String sessionId;
private List<String> errors;
public String getReqId() {
return reqId;
}
public void setReqId(String reqId) {
this.reqId = reqId;
}
public int getRetCode() {
return retCode;
}
public void setRetCode(int retCode) {
this.retCode = retCode;
}
public String getRetMsg() {
return retMsg;
}
public void setRetMsg(String retMsg) {
this.retMsg = retMsg;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public List<String> getErrors() {
return errors;
}
public void setErrors(List<String> errors) {
this.errors = errors;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
OK BaseBean 搞定了 下边撸接口
首先是万用的interface
public interface InternetService {
@POST("{path}")
Observable<BaseBean> requestPost(@Path("path")String path, @Body HashMap<String,Object> body);
@GET("{path}")
Observable<BaseBean> requestGet(@Path("path")String path, @Body HashMap<String,Object> body);
@Multipart
@POST("{path}")
Observable<BaseBean<List<ResponseUploadFiles>>> requestFile(@Path("path")String path, @Part List<MultipartBody.Part> list, @PartMap Map<String,RequestBody> requestBodyMap);
}
嗯 提供了三种方法
1.post请求 2.get请求 3.上传请求
那么问题来了 这样写的post和get数据 最后返回的BaseBean 的 data 并不能变成自己想要的!
怎么解决呢!参考了很多资料 然后找到了解决方法
重写Gson解析工厂 当然用了单例
/**
*
* 自定义GsonConverterFactory
*/
public class CustomizeGsonConverterFactory extends Converter.Factory {
private Gson gson;
private CustomizeGsonConverterFactory() {
gson=new GsonBuilder().registerTypeAdapter(BaseBean.class, BaseDeserializer.getInstance()).create();
}
private static class LazyHolder{
private static final CustomizeGsonConverterFactory INSTANCE=new CustomizeGsonConverterFactory();
}
public static final CustomizeGsonConverterFactory getInstance(){
return LazyHolder.INSTANCE;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomizeGsonResponseBodyConverter(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomizeGsonRequestBodyConverter(gson,adapter);
}
}
public class CustomizeGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
CustomizeGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
public class CustomizeGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
CustomizeGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
//把responsebody转为string
String response = value.string();
if (BuildConfig.DEBUG) {
//打印后台数据
System.out.println("response"+response);
}
HttpStatus status=gson.fromJson(response,HttpStatus.class);
//全局捕获token错误
if(status.isCodeInvalid()){
value.close();
throw new ApiException(status.getCode(),status.getMessage());
}
// BaseBean baseResponse = gson.fromJson(response, BaseBean.class);
// 这里只是为了检测code是否!=1,所以只解析HttpStatus中的字段,因为只要code和message就可以了
try {
return adapter.fromJson(response);
} finally {
value.close();
}
}
}
关于CustomizeGsonRequestBodyConverter 类之所以那么写是因为请求数据都是用的json形式
本来我的想法是 把Gson 对象json 动态设置的!结果经过测试 responseBodyConverter 和requestBodyConverter只会调用一次!
此路不通 换个思路 这里就涉及到一个东东自定义的JsonDeserializer 先上代码:
public class BaseDeserializer<Bean>implements JsonDeserializer<BaseBean> {
private BaseDeserializer(){}
private static class LazyHolder{
private static final BaseDeserializer INSTANCE=new BaseDeserializer();
}
public static BaseDeserializer getInstance(){
return LazyHolder.INSTANCE;
}
private Class<Bean> beanClass;
public BaseDeserializer setBeanClass(Class<Bean> beanClass) {
this.beanClass = beanClass;
return this;
}
@Override
public BaseBean<Bean> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
JsonArray errors=jsonObject.getAsJsonArray("errors");
JsonElement dataElement=jsonObject.get("data");
List<String> list=new ArrayList<>();
BaseBean baseBean=new BaseBean<>();
if(dataElement.isJsonArray()){
List<Bean> datas=new ArrayList<>();
JsonArray jsonDatas=jsonObject.getAsJsonArray("data");
for(JsonElement jsonElement:jsonDatas){
Bean data=context.deserialize(jsonElement,beanClass);
datas.add(data);
}
baseBean.setData(datas);
}else if(dataElement.isJsonNull()){
baseBean.setData(null);
}else{
baseBean.setData( context.deserialize(jsonObject.get("data").getAsJsonObject(),beanClass));
}
for(JsonElement jsonElement:errors){
JsonObject jsonOb = jsonElement.getAsJsonObject();
String error=jsonOb.getAsString();
errors.add(error);
}
JsonElement reqId=jsonObject.get("reqId");
JsonElement retCode=jsonObject.get("retCode");
JsonElement retMsg=jsonObject.get("retMsg");
JsonElement sessionId=jsonObject.get("sessionId");
baseBean.setReqId(reqId.isJsonNull()?"":reqId.getAsString());
baseBean.setRetCode(retCode.isJsonNull()?0:retCode.getAsInt());
baseBean.setRetMsg(retMsg.isJsonNull()?"":retMsg.getAsString());
baseBean.setSessionId(sessionId.isJsonNull()?"":sessionId.getAsString());
baseBean.setErrors(list);
return baseBean;
}
}
同样使用了单例 然后动态持有一个class对象 就是data的真正的bean !
主要是重写 deserialize方法 就是解析bean的过程 很简单 各位根据自己需要 自行更改
到这里问题已经解决了 上代码:
package com.nhcz500.base.net;
import com.nhcz500.base.Constants;
import com.nhcz500.base.model.BaseBean;
import com.nhcz500.base.model.ResponseUploadFiles;
import com.nhcz500.base.net.customize.BaseDeserializer;
import com.nhcz500.base.net.customize.CustomizeGsonConverterFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.xml.transform.Transformer;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.functions.Function;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
/**
* 单例retrofit工厂
*/
public class RetrofitManager {
private Retrofit retrofit;
private static long CONNECT_TIMEOUT = 10;
private AppInterceptor interceptor;
private RetrofitManager() {
interceptor=new AppInterceptor();
retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL) // 设置 网络请求 Url
.client(getOkHttpClient())
.addConverterFactory(CustomizeGsonConverterFactory.getInstance())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
.build();
}
private static final class LazyHolder {
private static final RetrofitManager INSTANCE = new RetrofitManager();
}
public static final RetrofitManager getInstance() {
return LazyHolder.INSTANCE;
}
/**
*获取返回类型
* @return
*/
public <T>Observable<BaseBean<T>> getRetrofitObservable(boolean post, String path, HashMap<String, Object> params, final Class beanClass) { //这里beanClass 之所以不用T 是为了防止有List类型的data部分
interceptor.setForm(false); //设置提交表单类型
InternetService service = retrofit.create(InternetService.class);
Observable<BaseBean> observable;
BaseDeserializer.getInstance().setBeanClass(beanClass);
// params.put("sessionId",RequestSingleton.getInstance().getSessionId());
if(post){
observable=service.requestPost(path, params);
}else{
observable=service.requestGet(path,params);
}
return observable.map(new Function<BaseBean,BaseBean<T>>() {
@Override
public BaseBean<T> apply(BaseBean baseBean) throws Exception {
return baseBean;
}
}).onTerminateDetach();
}
public Observable<BaseBean<List<ResponseUploadFiles>>> uploadFiles(String path, String fileParamsName,Map<String,String> params, String... filePaths) {
//我的项目中只有上传图片请求,上传其自行更改逻辑
interceptor.setForm(true);//设置提交表单类型
InternetService service = retrofit.create(InternetService.class);
BaseDeserializer.getInstance().setBeanClass(ResponseUploadFiles.class);
Map<String,RequestBody> map=new HashMap<>();
List<MultipartBody.Part> list=new ArrayList<>();
for (String filePath : filePaths) {
File file = new File(filePath);
//2、创建RequestBody,其中`multipart/form-data`为编码类型
RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpeg"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData(fileParamsName, file.getName(), requestFile);
System.out.println("file:"+file.getName());
list.add(body);
}
if(params!=null) {
for (String key : params.keySet()) {
map.put(key, createRequestBody(params.get(key)));
}
}
RequestBody sessionId = RequestBody.create(MediaType.parse("text/plain"),RequestSingleton.getInstance().getSessionId());
map.put("sessionId",sessionId);
return service.requestFile(path,list,map );
}
private RequestBody createRequestBody(String value){
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"),value);
return requestBody;
}
private OkHttpClient getOkHttpClient(){
return new OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(interceptor)
// .cookieJar(new CookiesManager())
.build();
}
}
OJBK 完美收工 怎么用?
HashMap<String,Object> params=new HashMap<>();
Observable<BaseBean<ResponseLanguage>>observable=RetrofitManager.getInstance()
.getRetrofitObservable(true,Constants.SYSTEM_LOCATION,params,ResponseLanguage.class);
是不是很简单!!