Rxjava2+okhttp3+Retrofit2封装
来源:互联网 发布:js用for作1 100 编辑:程序博客网 时间:2024/05/19 12:12
这里是Retrofit构造接口的方式,发现重复代码太多,我在网上找了个库,封装了一下,这是改造前部分接口,上次封装的有局限性,那个是根据接口号区分
如果带后缀就不好使了~
public interface UserServiceApi { @POST("api/login") Call<Result<User>> login(@Body WechatLoginRequest request); @POST("version/version") Call<Result<User>> update(@Body Update request); @POST("api/logout") Call<Result> logout(@Body BaseRequest request); @POST("api/user/info") Call<Result<User>> getOtherUserInfo(@Body BaseRequest request);}
封装改造后的api如下
public interface Api { String KEY = "data"; String PATH = "path"; @FormUrlEncoded @POST("{path}") Observable<String> runPost(@Path(value = PATH, encoded = true) String path, @Field(KEY) String json); @GET("{path}") Observable<String> runGet(@Path(value = PATH, encoded = true) String path, @Query(KEY) String json); @Streaming @GET Observable<ResponseBody> downFile(@Url() String url, @QueryMap Map<String, String> maps); @Multipart //@POST("/") @POST Observable<ResponseBody> uploadFiles(@Url() String url, @Part() List<MultipartBody.Part> parts);}
我把请求后缀放到请求实体上,采用注解的形式,测试时最大耗时2毫秒左右,不知道能不能接受这个时间
@Inherited@Documented@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface ObtainPath { public String value() default "";}
然后每一个请求体必须实现这个注解,首先我需要一个通用的请求体,姑且如下
@ObtainPath("")public class CommonReq implements Serializable { //里面可以放通用的请求参数 //比如渠道,版本号,等}
现在如何构建接口呢?
比如有如下接口
登录接口:https://api.github.com/user/login
注册接口:https://api.github.com/user/register
列表接口:https://api.github.com/user/list
更新接口:https://api.github.com/user/update
测试接口:https://api.github.com/user/test
这里请求格式是json,我需要构造请求体如下
登录
@ObtainPath("user/login")public class LoginReq extends CommonReq { public String name; // 用户名 public String password; // 密码}
注册
@ObtainPath("user/register") // 请求后缀在这里public class RegisterReq extends CommonReq {}
列表
@ObtainPath("user/list")public class ListReq extends CommonReq {}
更新
@ObtainPath("user/update")public class UpdateReq extends CommonReq {}
我觉得请求体肯定是少不掉的.响应体通样如此.
项目接口通用结构如下
可能返回这样 { "code": 1, // 我们后台大佬规定,1是成功,不是http code 200 "msg": "", "data": {} }也可能返回这样 { "code": 1, // 我们后台大佬规定,1是成功,不是http code 200 "msg": "", "data": [] }
抽取通用代码
public class CommonResp implements Serializable { public static final long serialVersionUID = 1L; public int code; public String msg; public boolean isSuccess() { return code == 1; // 1 成功 -1 失败 -2 退出登录 }}
如果data
返回的是对象
public class HttpCommonObjResp<T> extends CommonResp { private static final long serialVersionUID = 1L; public T data; // 我喜欢用public,不用get set 方式获取它 }
如果data
返回的是数组对象,我定义如下
public class HttpCommonResp<T> extends CommonResp { public List<T> data; public List<T> getDatas() { if (data == null) { data = new ArrayList<T>(); } return data; }}
到此,通用的请求体,通用的响应体已经全部构造完毕
接下来是调用方式:
比如我们的其中一个接口返回数据如下
{ "code": 1, "msg": "", "data": { "id": "4", "channel": "yingyongbao", "vnumber": "10", "url": "http://shangjie888.oss-cn-shanghai.aliyuncs.com/release-v1.6.5-yingyongbao.apk", "content": "1.修正" "platform": "android", "force": 0, "name": null, "switch": "1", // 这尼玛关键字,不知道干嘛使的,我一直没用它,可以不关注它,这个字段鬼知道干嘛的.... "versionnum": "1.6.5" }}
data
是对象
我需要把这个对象封装,很多接口,需要很多对象,这里我在封装一个基对象,什么都不干,只实现序列化接口,跳转携带对象好用,不用Parcelable接口,懒得写
public class BaseBean implements Serializable { public String channel; // 呵呵}
public class UpdateResp extends BaseBean { public String id; // public String channel; // 这个通用的么,给它爹 public String vnumber; public String content; public String name; public String platform;}
这里算是封装好一个接口的数据了,姑且叫更新接口,怎么调用?
这里有2种方式
1.你可以获取String 自己手动解析
2.你可以指定返回体data
方式一:
HttpRequestFactory.doPost(new UpdateReq(), new ResultCallbackAdapterIs<String>(this) { // this代表activity @Override public void doOnError(ApiException ex) { super.doOnError(ex); // 这里,activity.isFinishing(); 不会走成功和失败回调的 } @Override public void doOnResponse(String response) { super.doOnResponse(response); // 自己手动解析 } }, null); // null 这里填的是加载框,如有需要
方式二:
data
是对象,所以用HttpCommonObjResp<T>
T就是data
对象
HttpRequestFactory.doPost(new UpdateReq(), new ResultCallbackAdapterIs<HttpCommonObjResp<UpdateResp>>(this) { @Override public void doOnResponse(HttpCommonObjResp<UpdateResp> response) { super.doOnResponse(response); if (response.isSuccess()) { UpdateResp resp = response.data; } else { // error } } }, ll);
如果是这样呢?
{ "code": 1, "msg": "", "data":[] // 数组对象,咋弄}
data
是数组对象,所以用HttpCommonResp<T>
T就是data
数组对象(集合对象)
HttpRequestFactory.doPost(new UpdateReq(), new ResultCallbackAdapterIs<HttpCommonResp<UpdateResp>>(this) { @Override public void doOnResponse(HttpCommonResp<UpdateResp> response) { super.doOnResponse(response); if (response.isSuccess()) { List<UpdateResp> resp = response.data; // 看好了,是List<T>接受 } else { // error } } }, null); // null这里是加载框,可以不用,但是要有
其中代码关于缓存,暂时并没有处理~~~
这是HttpRequestFactory的核心代码,获取请求后缀
public static <T> void exec(Object obj, ResultCallback<T> mCallback, boolean isPost, ILoadingI mILoadingI) { if (obj == null) { throw new RuntimeException("请求体不能为空~"); } String pathPostfix = ""; if (obj instanceof CommonReq) { long start = SystemClock.currentThreadTimeMillis(); CommonReq common = (CommonReq) obj; ObtainPath mObtainPath = common.getClass().getAnnotation( ObtainPath.class); pathPostfix = mObtainPath.value(); long end = SystemClock.currentThreadTimeMillis(); Log.e(TAG, "##解析耗时##" + (end - start) + "##毫秒##" + (end - start) / 1000 + "##秒##"); if (TextUtils.isEmpty(pathPostfix)) { throw new RuntimeException("网络请求路径后缀不能为空!~"); } } else { throw new RuntimeException("请求类型必须是CommonReq 或者 其子类吆~"); } if (!Network.isConnected(HttpLib.getContext())) { // ToastTool.showNetisDead(HttpLib.getContext()); // 没有网络 if (mILoadingI != null && mILoadingI.isShowingI()){ mILoadingI.beginDismiss(); //加载框 } return; } // 发起网络请求 dowork...... // .... if(isPost){ HttpRequestManager.doPost(pathPostfix, obj, mCallback,mILoadingI); } else { HttpRequestManager.doGet(pathPostfix, obj, mCallback,mILoadingI); } }
用法
allprojects { repositories { ... maven { url 'https://jitpack.io' } } } dependencies { compile 'com.github.majunm.http:http:v1.0.31' }
也可以移步github
源码下载地址
- Rxjava2+okhttp3+Retrofit2封装
- Retrofit2+OkHttp3+RxJava2
- Okhttp3+Rxjava+Retrofit2封装
- retrofit2+rxjava2封装解析
- 简单封装retrofit2+rxjava2
- rxjava2 + retrofit2 + okhttp3遇到的问题
- RxJava2+Retrofit2+OkHttp3实现网络缓存
- (9)RxJava2+Retrofit2+OkHttp3系列(OkHttp3-1)
- (1)RxJava2+Retrofit2+OkHttp3系列(RxJava2-1)
- (2)RxJava2+Retrofit2+OkHttp3系列(RxJava2-2)
- (3)RxJava2+Retrofit2+OkHttp3系列(RxJava2-3)
- (4)RxJava2+Retrofit2+OkHttp3系列(RxJava2-4)
- (5)RxJava2+Retrofit2+OkHttp3系列(RxJava2-5)
- (6)RxJava2+Retrofit2+OkHttp3系列(RxJava2-6)
- (7)RxJava2+Retrofit2+OkHttp3系列(RxJava2-7)
- retrofit2+okhttp3+rxjava网络封装
- RxJava2 + Retrofit2 优雅简洁封装
- Retrofit2+Rxjava2联网的封装
- HTML5--使用外链式为div标签设置属性
- 计算题
- kettle案例四使用java脚本进行数据处理
- Uboot中start.S源码解析
- adb 查询当前包名
- Rxjava2+okhttp3+Retrofit2封装
- <init>和<clinit>的区别
- 写时拷贝
- word文档编辑问题
- jvm--5 类的加载过程
- Codeforces Round #228 Div.1 D 数位dp+数学
- 队列的链队子函数
- Wannafly挑战赛4 D 树的距离
- 史上最全的ubuntu16.04安装nvidia驱动+cuda9.0+cuDnn7.0