前述
Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,适合Restful 风格的接口,但是非RESTful API 如何使用呢?
RESTful API 如下:
{
"name": "Hello",
"uid": 1
}
Not RESTful API,添加了自定义的返回码(code)和返回信息(msg),数据等:
{
"code": 0,
"msg": "success",
"data": {
"uid": 1,
"name": "Hello"
}
}
Retrofit的基础用法
1. 定义Java interface
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
2. 创建Retrofit,生成GitHubService接口的实现
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
3.向远程Web服务器发出同步或异步HTTP请求,返回响应
Call<List<Repo>> repos = service.listRepos("octocat");
//异步
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call,
Response<List<Repo>> response) {
}
@Override
public void onFailure(Call<List<Repo>> call,
Throwable t) {
}
});
Retrofit回调处理
Retrofit的处理一般有2种处理方法
1.自定义(重写)ResponseConverter
2.自定义(重写)CallBack
ResponseConverter
拿GsonConverterFactory来说,由三个类组成:
GsonConverterFactory // GsonConverter 工厂类, 用来创建GsonConverter
GsonResponseBodyConverter // 处理ResponseBody
GsonRequestBodyConverter // 处理RequestBody
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
查看GsonRequestBodyConverter的代码
@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());
}
将Java 对象写成Json,生成一个RequestBody对象
当我们发出一个POST JSON请求(直接用Retrofit post一个实体给服务器,请求的时候会自动将我们的实体转成Json)的时候,Retrofit就会调用GsonRequestBodyConverter的Convert方法将我们的实体转换成json
GsonResponseBodyConverter
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
而接受服务器返回的数据时,Retrofit会调用GsonResponseBodyConverter将Json数据转换成我们需要的实体
需要重写的就是GsonResponseBodyConverter,
public class CustomResponseConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
public CustomResponseConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
try {
String body = value.string();
JSONObject json = new JSONObject(body);
int ret = json.optInt("code");
String msg = json.optString("msg", "");
if (ret == 0) {
if (json.has("data")) {
Object data = json.get("data");
body = data.toString();
return adapter.fromJson(body);
} else {
return (T) msg;
}
} else {
throw new RuntimeException(msg);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
value.close();
}
}
}
再写一个CustomConverterFactory
public final class CustomConverterFactory extends Converter.Factory {
public static CustomConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static CustomConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new CustomConverterFactory(gson);
}
private final Gson gson;
private CustomConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomResponseConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
在 new Retrofit.Builder().addConverterFactory(CustomConverterFactory.create()) 就可以了,想要了解更多,可以参考这篇文章
CallBack的处理
普通处理
1.统一返回类
public class HttpResult<T> {
private String result_code;
private String error;
private Option option;
private T data;
}
2.Java Interface
@FormUrlEncoded
@POST("create_auth/")
Call<HttpResult<String>> postGetData(@FieldMap Map<String, String> param);
3.回调重写
public abstract class HttpCallBack<T> implements Callback<HttpResult<T>> {
private final int RESPONSE_CODE_FAILED = -1; //返回数据失败
private Gson gson = new Gson();
private Context mContext;
public HttpCallBack(Context mContext){
this.mContext = mContext;
}
@Override
public void onResponse(Call<HttpResult<T>> call, Response<HttpResult<T>> response) {
if (response.isSuccessful()) {// code >=200 && code <300
String responseCode = response.body().getResult_code();
Log.e("responseCode",""+responseCode);
Log.e("responseString",""+response.body().toString());
Log.e("responseData",""+response.body().getData());
// //responseCode是业务api 里面定义的,根据responseCode进行进一步的数据和事件分发
if (responseCode != null){
if ( responseCode.equals("SECCUSEE_CODE")){
onSuccess(response.body().getData());
}else{
onFailure(responseCode,response.body().getError());
}
}
}else {
//================ 1.handle http default error 4xx,5xx=================
int code = response.raw().code();
String message = response.raw().message(); //code 和 message 都是http Raw 数据,你抓包就能看见的
Log.e("http-error", "code:" + code + " message:" + message);
String errorBodyStr = "";
try {
errorBodyStr = response.errorBody().string();
} catch (IOException e) {
e.printStackTrace();
}
try {
HttpResult errorResponse = gson.fromJson(errorBodyStr, HttpResult.class);
if (null != errorResponse) {
onFailure(errorResponse.getResult_code(), errorResponse.getError());
//这里的code 如果定义和public void onFailure(Call<T> call, Throwable t) { 一样,要记得分开处理
} else {
onFailure(RESPONSE_CODE_FAILED+"", "ErrorResponse is null ");
}
} catch (Exception jsonException) {
onFailure(RESPONSE_CODE_FAILED+"", "http请求错误Json 信息异常"); //
jsonException.printStackTrace();
}
}
}
@Override
public void onFailure(Call<HttpResult<T>> call, Throwable t) {
String temp = t.getMessage();
Log.e("OnFailure",call.toString()+"=="+t.getMessage());
String errorMessage = "Data Receiver Fail" + temp;
if (t instanceof SocketTimeoutException){
errorMessage = "服务器响应超时";
} else if(t instanceof ConnectException){
errorMessage = "网络连接异常,请检查网络";
}else if (t instanceof RuntimeException) {
errorMessage = "运行时错误";
} else if (t instanceof UnknownHostException) {
errorMessage = "无法解析主机,请检查网络连接";
}else if (t instanceof UnknownServiceException){
errorMessage = "未知的服务器错误";
}
onFailure(RESPONSE_CODE_FAILED + "",errorMessage);
}
public abstract void onSuccess(T t);
public void onFailure(String responseCode, String error) {
if (responseCode.equals(RESPONSE_CODE_FAILED+"") && mContext != null) {
ToastUtils.getInstanc(mContext).showToast(error);
}
}
}
4.调用
Call<HttpResult<String>> resultCall = service.postGetData(params);
//异步
resultCall.enqueue(new HttpCallBack<String>(this) {
@Override
public void onSuccess(String s) {
}
@Override
public void onFailure(Call<HttpResult<String>> call, Throwable t) {
super.onFailure(call, t);
}
});
至此结束
参考博客:
Retrofit 巧妙的回调封装
Retrofit–合理封装回调能让你的项目高逼格
Retrofit自定义GsonConverter处理所有请求错误情况
Retrofit统一处理服务器返回参数
深入浅出 Retrofit,这么牛逼的框架你们还不来看看
RxJava 与 Retrofit 结合的最佳实践