Retrofit网络通信库简单封装使用
2016-06-28 13:46
537 查看
Retrofit 这个网络库相信用过的都能体会到它的强大,这个库本身已经封装的很优雅了,注解使用起来也很方便,这里我再对这个库封装是为了方便公司接口使用而进行的。注意,这里没有使用Rxjava转换,用的是Gson转换,因为公司项目并没有导入Rxjava,所以都用Gson来处理。
源代码地址:https://github.com/Rukey7/RetrofitSample
一般公司的接口返回的数据都有一个固定格式,举个简单例子:
一. Retrofit的使用
具体格式有了,下面就开始编写Api接口了。首先定义一个统一格式的返回实体,对照上面的Json格式如下:
下面定义两个请求接口,一个返回实体,一个返回列表:
二. 封装接口
首先来把Gson数据处理的功能封装成一个帮助类:
功能还是比较清晰的,主要就是对泛型的处理,分别提供了转换实体和实体列表两个主要方法,用来转化Gson数据还是很方便的。
接下来对CallBack<BaseResponse>也进行一层封装,如下:
下面自定义个监听器用来获取我们需要的数据:
现在只差一个功能模块,就是把Call请求、Gson数据和OnRequestListener监听器关联起来,下面是这个功能模块的代码:
该写的都写好了,下面就看怎么调用了,比如我们要使用获取单个用户信息接口,可以这样写:
写的有点晕,有兴趣看下代码估计更好理解- -,其它的网络缓存和请求取消控制管理看具体业务怎么处理再加上去。
源代码地址:https://github.com/Rukey7/RetrofitSample
一般公司的接口返回的数据都有一个固定格式,举个简单例子:
{ "data": {.... }, "msg": "获取数据成功", "status": "1" }这里的字段,status:返回为请求是否成功;msg:描述信息;data:返回的具体请求数据,可能是一个实体或一个列表,上面返回的是一个实体。返回列表的格式如下:
{ "data": [ {.... }, {.... } ], "msg": "获取数据成功", "status": "1" }
一. Retrofit的使用
具体格式有了,下面就开始编写Api接口了。首先定义一个统一格式的返回实体,对照上面的Json格式如下:
public class BaseResponse { private String status; private String msg; private Object data; public Object getData() { return data; } public void setData(Object data) { this.data = data; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } @Override public String toString() { return "BaseResponse{" + "status='" + status + '\'' + ", msg='" + msg + '\'' + ", data=" + data + '}'; } }这里需要注意的是data字段要用Object不能用String,我用Gson再将String数据解析为实体时会报错,不知道是不是我写的问题,我用fastjson就没问题,所以这里用Object类型。
下面定义两个请求接口,一个返回实体,一个返回列表:
public interface IUserService { @GET("user/your") Call<BaseResponse> user(@Query("id") int id); @GET("users/your/list") Call<BaseResponse> userList(@Query("param") String param); }来看一下我们正常使用流程,比如获取user信息接口:
public void userInfo() { // 创建Retrofit Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .baseUrl("https://api.yoururl.com/") .build(); // 创建IUserService IUserService userService = retrofit.create(IUserService.class); // 创建请求 Call<BaseResponse> call = userService.user(10086); // 执行请求 call.enqueue(new Callback<BaseResponse>() { @Override public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) { Gson gson = new Gson(); try { BaseResponse body = response.body(); // 先判断状态值 if (body.getStatus().equals("1")) { // 将Object对象转化为json字符串 String jsonData = gson.toJson(body.getData()); // 将json字符串转化为对象实体 UserInfo info = gson.fromJson(jsonData, UserInfo.class); // 判断解析是否成功 if (info == null) { onFailure(call, new Throwable("对象解析失败")); } else { // 获取到数据,开始处理数据 } } else { onFailure(call, new Throwable(body.getMsg())); } } catch (Exception e) { onFailure(call, e); } } @Override public void onFailure(Call<BaseResponse> call, Throwable t) { // 失败处理 } }); }整个代码调用算是正常流程,这里面肯定有很多冗余代码可以提取出来,看下怎么封装让接口使用更简单,下面开始对接口进行封装。
二. 封装接口
首先来把Gson数据处理的功能封装成一个帮助类:
public final class GsonHelper { private static Gson sGson = new Gson(); private static JsonParser sJsonParser = new JsonParser(); /** * 将json数据转化为实体数据 * @param jsonData json字符串 * @param entityClass 类型 * @return 实体 */ public static <T> T convertEntity(String jsonData, Class<T> entityClass) { T entity = null; try { entity = sGson.fromJson(jsonData.toString(), entityClass); } catch (JsonSyntaxException e) { e.printStackTrace(); } return entity; } /** * 将json数据转化为实体列表数据 * @param jsonData json字符串 * @param entityClass 类型 * @return 实体列表 */ public static <T> List<T> convertEntities(String jsonData, Class<T> entityClass) { List<T> entities = new ArrayList<>(); try { JsonArray jsonArray = sJsonParser.parse(jsonData).getAsJsonArray(); for (JsonElement element : jsonArray) { entities.add(sGson.fromJson(element, entityClass)); } } catch (JsonSyntaxException e) { e.printStackTrace(); } return entities; } /** * 将 Object 对象转为 String * @param jsonObject json对象 * @return json字符串 */ public static String object2JsonStr(Object jsonObject) { return sGson.toJson(jsonObject); } }
功能还是比较清晰的,主要就是对泛型的处理,分别提供了转换实体和实体列表两个主要方法,用来转化Gson数据还是很方便的。
接下来对CallBack<BaseResponse>也进行一层封装,如下:
/** * 对CallBack进行封装 */ public abstract class RequestCallBack implements Callback<BaseResponse> { // 请求成功是的状态值 private static final String RESPONSE_SUCC = "1"; // 请求失败是的状态值 private static final String RESPONSE_FAIL = "-1"; // 测试用 public static boolean mIsList = false; @Override public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) { BaseResponse body = response.body(); _handleResponse(body); } @Override public void onFailure(Call<BaseResponse> call, Throwable t) { t.printStackTrace(); onError(t.getMessage()); } /** * 处理应答 * @param response 应答实体 */ private void _handleResponse(BaseResponse response) { try { if (RESPONSE_SUCC.equals(response.getStatus())) { // 请求成功才处理数据 onDataObtain(GsonHelper.object2JsonStr(response.getData())); } else { onError(response.getMsg()); } } catch (Exception e) { if (e.getMessage() == null) { onError("thread exiting with uncaught exception"); } else { onError(e.getMessage()); } } } /** * 获取json数据 * @param jsonData json字符串 * @return */ protected abstract void onDataObtain(String jsonData); /** * 获取错误数据 * @param errMsg 错误数据 */ protected abstract void onError(String errMsg); }这里主要工作是从BaseResponse实体中提取出data数据,并转换为json字符串格式传给上层进一步处理,这里也对异常情况进行了初步处理。当然,可能根据实际需要对BaseResponse数据进行更加细致的处理,这个就看实际需求来处理了。
下面自定义个监听器用来获取我们需要的数据:
/** * 请求监听器 */ public interface OnRequestListener<T> { /** * 获取请求实体数据 * @param entity 实体 */ void onResponse(T entity); /** * 请求失败 * @param errorMsg 异常数据 */ void onFailure(String errorMsg); }这个没什么好说明的,就是有个泛型处理,等下用到就知道了。
现在只差一个功能模块,就是把Call请求、Gson数据和OnRequestListener监听器关联起来,下面是这个功能模块的代码:
/** * 请求处理的通用模块 */ public final class ServiceHelper { private ServiceHelper() { throw new RuntimeException("ServiceHelper cannot be initialized!"); } /** * 获取单个实体的处理操作 * * @param call 请求 * @param entityClass 实体类型 * @param listener 监听器 */ public static <T> void callEntity(Call<BaseResponse> call, final Class<T> entityClass, final OnRequestListener<T> listener) { call.enqueue(new RequestCallBack() { @Override protected void onDataObtain(String jsonData) { T info = GsonHelper.convertEntity(jsonData, entityClass); if (info == null) { if (listener != null) { listener.onFailure("对象解析失败"); } } else { if (listener != null) { listener.onResponse(info); } } } @Override protected void onError(String errMsg) { if (listener != null) { listener.onFailure(errMsg); } } }); } /** * 获取复数实体的处理操作 * * @param call 请求 * @param entityClass 实体类型 * @param listener 监听器 */ public static <T> void callEntities(Call<BaseResponse> call, final Class<T> entityClass, final OnRequestListener<List<T>> listener) { call.enqueue(new RequestCallBack() { @Override protected void onDataObtain(String jsonData) { List<T> infos = GsonHelper.convertEntities(jsonData, entityClass); if (infos.size() == 0) { if (listener != null) { listener.onFailure("对象解析失败"); } } else { if (listener != null) { listener.onResponse(infos); } } } @Override protected void onError(String errMsg) { if (listener != null) { listener.onFailure(errMsg); } } }); } }这里提供两个方法,一个用来获取单个实体,一个用来获取实体列表,还是很清晰的。这里同样对泛型进行了处理,并把前面几样东西都关联了起来,所有功能都通过这里进入来处理,包括执行请求->解析对象->调用监听回调。
该写的都写好了,下面就看怎么调用了,比如我们要使用获取单个用户信息接口,可以这样写:
/** * 获取单个实体 * @param id 参数 * @param listener 请求监听 * @return 通信回调接口,用来取消通信 */ public static Call userInfo(int id, OnRequestListener<UserInfo> listener) { Call<BaseResponse> call = sUserService.user(id); ServiceHelper.callEntity(call, UserInfo.class, listener); return call; }获取用户列表接口这样写:
/** * 获取实体列表 * @param param 参数 * @param listener 请求监听 * @return 通信回调接口,用来取消通信 */ public static Call userList(String param, OnRequestListener<List<UserInfo>> listener) { Call<BaseResponse> call = sUserService.userList(param); ServiceHelper.callEntities(call, UserInfo.class, listener); return call; }可以看到整个实际只要两行代码:生成一个call请求;使用ServiceHelper执行请求并解析数据。没了!还是很方便的有木有。
写的有点晕,有兴趣看下代码估计更好理解- -,其它的网络缓存和请求取消控制管理看具体业务怎么处理再加上去。
相关文章推荐
- HDU 3572 网络流
- 如何绘制caffe网络训练曲线
- 如何绘制caffe网络训练曲线
- 社交网络中信息内容的计算公式
- Linux centos 下apache(httpd)编译安装
- jQuery网络请求及JSON数据处理
- Linux网络配置脚本
- Volley网络框架的简单使用
- java常用的发送http请求的工具方法
- 添物不花钱学计算机及编程(预备篇) - 计算机网络
- 添物不花钱学计算机及编程(预备篇) - 计算机网络
- 基于java的https双向认证,android上亦可用
- volley网络请求保持sessionID
- 安卓网络请求之——OkHttp学习
- Wireshark分析网络慢
- Android HttpUtils网络请求工具类的实现
- 设置http响应头Cache-Control及Pragma,增加CDN cache命中率
- 网络七层
- 日常小结-配置https连接器
- iOS 自己封装的网络请求,json解析的类