赞
踩
一个功能强悍的网络请求库,使用RxJava2 + Retrofit2 + OKHttp组合进行封装。还不赶紧点击使用说明文档,体验一下吧!
项目地址
https://github.com/xuexiangjys
服务端的搭建详细请点击查看
目前支持主流开发工具AndroidStudio的使用,直接配置build.gradle,增加依赖即可.
1.先在项目根目录的 build.gradle 的 repositories 添加:
- allprojects {
- repositories {
- ...
- maven { url "https://jitpack.io" }
- }
- }
2.然后在dependencies添加:
- dependencies {
- ...
- implementation 'com.github.xuexiangjys:XHttp2:1.0.2'
- implementation 'com.google.code.gson:gson:2.8.2'
- implementation 'com.squareup.okhttp3:okhttp:3.10.0'
- implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
- implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
- }
3.在Application中初始化XHttpSDK
- XHttpSDK.init(this); //初始化网络请求框架,必须首先执行
- XHttpSDK.debug("XHttp"); //需要调试的时候执行
- XHttpSDK.setBaseUrl(SettingSPUtils.getInstance().getApiURL()); //设置网络请求的基础地址
4.全局初始化配置(非必要)
除了上述的操作以外,你还可以使用XHttp.getInstance()对网络请求框架进行全局性参数配置,配置一些公用默认的参数,这样我们就不需要为每个请求都进行设置。方法如下:
方法名 | 备注 :-|:- debug | 设置日志的打印模式 setBaseUrl | 设置全局baseUrl setSubUrl | 设置全局subUrl setReadTimeOut | 设置全局读取超时时间 setWriteTimeOut | 设置全局写入超时时间 setConnectTimeout | 设置全局连接超时时间 setTimeout | 设置全局超时时间 setRetryCount | 设置全局超时重试次数 setRetryDelay | 设置全局超时重试延迟时间 setRetryIncreaseDelay | 设置全局超时重试延迟叠加时间 setCacheMode | 设置全局的缓存模式 setIsDiskCache | 设置是否是磁盘缓存 setMemoryMaxSize | 设置内存缓存的最大数量 setCacheTime | 设置全局的缓存过期时间 setCacheMaxSize | 设置全局的磁盘缓存大小,默认50M setCacheDirectory | 设置全局缓存的路径,默认是应用包下面的缓存 setCacheDiskConverter | 设置全局缓存的转换器 addCommonParams | 添加全局公共请求参数 addCommonHeaders | 添加全局公共请求参数 addInterceptor | 添加全局拦截器 addNetworkInterceptor | 添加全局网络拦截器 setOkproxy | 全局设置OkHttpClient的代理 setOkconnectionPool | 设置全局OkHttpClient的请求连接池 setOkclient | 全局为Retrofit设置自定义的OkHttpClient addConverterFactory | 设置全局Converter.Factory,默认GsonConverterFactory.create() addCallAdapterFactory | 设置全局CallAdapter.Factory,默认RxJavaCallAdapterFactory.create() setHostnameVerifier | 设置https的全局访问规则 setCertificates | 设置https的全局自签名证书 setCookieStore | 设置全局cookie存取规则
需要注意的是,所以请求返回的结果必须要满足以下格式:
- {
- "Code":0, //响应码,0为成功,否则失败
- "Msg":"", //请求失败的原因说明
- "Data":{} //返回的数据对象
- }
约定了其中Code、Msg、Data首字母必须大写,否则无法解析成功。
需要自定义返回的实体API请点击查看
1.使用XHttp.post、XHttp.get、XHttp.delete、XHttp.put、XHttp.downLoad构建请求。
2.修改request的请求参数。
方法名 | 类型 | 默认值 | 备注 :-|:-:|:-:|:- baseUrl | String | / | 设置该请求的baseUrl timeOut | long | 10000 | 设置超时时间 accessToken | boolean | false | 是否需要验证token threadType | String | / | 设置请求的线程调度类型 syncRequest | boolean | false | 设置是否是同步请求(不开子线程) onMainThread | boolean | true | 请求完成后是否回到主线程 upJson | String | "" | 上传Json格式的数据请求 keepJson | boolean | false | 返回保持json的形式 retryCount | int | / | 设置超时重试的次数 retryDelay | int | / | 设置超时重试的延迟时间 retryIncreaseDelay | int | / | 设置超时重试叠加延时 headers | HttpHeaders | / | 添加头信息 params | HttpParams | /| 设置表单请求参数 cacheMode | CacheMode | CacheMode.NO_CACHE | 设置缓存的模式
3.调用execute方法执行请求。execute一般有如下两种方式:
4.请求使用演示
- XHttp.get("/user/getAllUser")
- .syncRequest(false) //异步请求
- .onMainThread(true) //回到主线程
- .execute(new SimpleCallBack<List<User>>() {
- @Override
- public void onSuccess(List<User> response) {
- refreshLayout.finishRefresh(true);
- if (response != null && response.size() > 0) {
- mUserAdapter.refresh(response);
- mLlStateful.showContent();
- } else {
- mLlStateful.showEmpty();
- }
- }
- @Override
- public void onError(ApiException e) {
- refreshLayout.finishRefresh(false);
- mLlStateful.showError(e.getMessage(), null);
- }
-
- });
- XHttp.post("/user/deleteUser")
- .params("userId", item.getUserId())
- .execute(Boolean.class)
- .subscribeWith(new TipRequestSubscriber<Boolean>() {
- @Override
- protected void onSuccess(Boolean aBoolean) {
- ToastUtils.toast("删除成功!");
- setFragmentResult(RESULT_OK, null);
- popToBack();
- }
- });

在使用它之前,需要下载/定义对应的实体协议,如下:
- @RequestParams(url = "/user/addUser", accessToken = false)
- public static class UserService_AddUser extends XHttpRequest {
-
- /**
- *
- */
- public User request;
-
- @Override
- protected Boolean getResponseEntityType() {
- return null;
- }
- }
1.注解说明
注解参数 | 类型 | 默认值 | 备注 :-|:-:|:-:|:- baseUrl | String | "" | 设置该请求的baseUrl url | String | "" | 请求网络接口地址 timeout | long | 15000 | 设置超时时间 accessToken | boolean | true | 设置是否需要验证token cacheMode | CacheMode | CacheMode.NO_CACHE | 设置请求的缓存模式
注解参数 | 类型 | 默认值 | 备注 :-|:-:|:-:|:- key | String | / | 请求参数的key
2.使用XHttpSDK进行请求。
executeToMain(XHttpRequest xHttpRequest): 执行post请求,返回observable对象(主线程->主线程)executeToMain(XHttpRequest xHttpRequest,BaseSubscriber<T> subscriber): 执行post请求并进行订阅,返回订阅信息(主线程->主线程)3.请求使用演示。
- XHttpRequest req = ApiProvider.getAddUserReq(getRandomUser());
- XHttpSDK.executeToMain(req, new ProgressLoadingSubscriber<Boolean>(mIProgressLoader) {
- @Override
- public void onSuccess(Boolean aBoolean) {
- ToastUtils.toast("用户添加成功!");
- mRefreshLayout.autoRefresh();
- }
- });
在使用它之前,需要下载/定义对应的接口协议,如下:
- /**
- * 订单
- */
- public interface IOrder {
- /**
- * 购买书
- *
- * @param bookId 用户名
- * @param userId 密码
- */
- @NetMethod(ParameterNames = {"bookId", "userId", "number"}, Url = "/order/addOrder/")
- Observable<Boolean> buyBook(int bookId, int userId, int number);
- }
1.注解说明
注解参数 | 类型 | 默认值 | 备注 :-|:-:|:-:|:- ParameterNames | String[] | {} | 参数名集合 BaseUrl | String | "" | 设置该请求的baseUrl Url | String | "" | 请求网络接口地址 Timeout | long | 10000 | 设置超时时间 AccessToken | boolean | true | 设置是否需要验证token CacheMode | CacheMode | CacheMode.NO_CACHE | 设置请求的缓存模式
2.使用XHttpProxy进行请求。
构建一个XHttpProxy,将定义的api接口传入后,直接调用接口进行请求。
构造XHttpProxy可以传入isPostJson来决定请求是上传json数据还是键值对数据, 默认是true,上传json数据。
构造XHttpProxy可以传入ThreadType,默认是ThreadType.TO_MAIN。
【注意】请确保网络请求在主线程中【实质是异步请求(切换到io线程),且响应的线程又切换至主线程】
【注意】请确保网络请求在主线程中【实质是异步请求(切换到io线程),不过响应的线程不变,还是之前请求的那个io线程】
【注意】请确保网络请求在子线程中才可以使用该类型【实质是不做任何线程调度的同步请求】
3.请求使用演示。
- //使用XHttpProxy进行接口代理请求
- XHttpProxy.proxy(TestApi.IOrder.class)
- .buyBook(mBookAdapter.getItem(position).getBookId(), UserManager.getInstance().getUser().getUserId(), 1)
- .subscribeWith(new TipRequestSubscriber<Boolean>() {
- @Override
- public void onSuccess(Boolean aBoolean) {
- ToastUtils.toast("图书购买" + (aBoolean ? "成功" : "失败") + "!");
- mRefreshLayout.autoRefresh();
- }
- });
1.文件上传【multipart/form-data】
使用post的文件表单上传。使用XHttp.post,然后使用params传递附带的参数,使用uploadFile传递需要上传的文件,使用示例如下:
- mIProgressLoader.updateMessage("上传中...");
- XHttp.post("/book/uploadBookPicture")
- .params("bookId", book.getBookId())
- .uploadFile("file", FileUtils.getFileByPath(mPicturePath), new IProgressResponseCallBack() {
- @Override
- public void onResponseProgress(long bytesWritten, long contentLength, boolean done) {
-
- }
- }).execute(Boolean.class)
- .compose(RxLifecycle.with(this).<Boolean>bindToLifecycle())
- .subscribeWith(new ProgressLoadingSubscriber<Boolean>(mIProgressLoader) {
- @Override
- public void onSuccess(Boolean aBoolean) {
- mIsEditSuccess = true;
- ToastUtils.toast("图片上传" + (aBoolean ? "成功" : "失败") + "!");
- }
- });

2.文件下载
使用XHttp.downLoad,传入下载的地址url、保存文件的路径以及文件名即可完成文件的下载,使用示例如下:
- XHttp.downLoad(BookAdapter.getBookImgUrl(book))
- .savePath(PathUtils.getExtPicturesPath())
- .execute(new DownloadProgressCallBack<String>() {
- @Override
- public void onStart() {
- HProgressDialogUtils.showHorizontalProgressDialog(getContext(), "图片下载中...", true);
- }
-
- @Override
- public void onError(ApiException e) {
- ToastUtils.toast(e.getMessage());
- HProgressDialogUtils.cancel();
- }
-
- @Override
- public void update(long bytesRead, long contentLength, boolean done) {
- HProgressDialogUtils.onLoading(contentLength, bytesRead); //更新进度条
- }
-
- @Override
- public void onComplete(String path) {
- ToastUtils.toast("图片下载成功, 保存路径:" + path);
- HProgressDialogUtils.cancel();
- }
- });

1.请求loading加载和请求生命周期绑定
在请求时,订阅ProgressLoadingSubscriber或者ProgressLoadingCallBack,传入请求消息加载者IProgressLoader,即可完成生命周期的绑定。示例如下:
- XHttpRequest req = ApiProvider.getAddUserReq(getRandomUser());
- XHttpSDK.executeToMain(req, new ProgressLoadingSubscriber<Boolean>(mIProgressLoader) {
- @Override
- public void onSuccess(Boolean aBoolean) {
- ToastUtils.toast("用户添加成功!");
- mRefreshLayout.autoRefresh();
- }
- });
2.网络请求生命周期和Activity/Fragment生命周期绑定
(1)这里需要依赖一下RxUtil2
implementation 'com.github.xuexiangjys:rxutil2:1.1.2'
(2)在所在的Activity的onCreate()下锁定Activity.
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- RxLifecycle.injectRxLifecycle(this);
- }
(3)然后在请求中使用RxJava的compose的操作符进行绑定。
.compose(RxLifecycle.with(this).<Boolean>bindToLifecycle())
(1)框架默认提供一个实现好的日志拦截器HttpLoggingInterceptor,通过XHttpSDK.debug("XHttp");就可以设置进去,它有5种打印模式
(2)如果需要对网络请求的相关参数进行自定义记录的话,可以继承HttpLoggingInterceptor实现一个自己的网络请求日志拦截器,重写logForRequest和logForResponse两个方法即可。
(3)设置自定义的日志拦截器.
XHttpSDK.debug(new CustomLoggingInterceptor());
有时候,我们需要对所有请求添加一些固定的请求参数,但是这些参数的值又是变化的,这个时候我们就需要动态添加请求参数【例如,请求的token、时间戳以及签名等】
(1)继承BaseDynamicInterceptor,实现updateDynamicParams方法,如下:
- @Override
- protected TreeMap<String, Object> updateDynamicParams(TreeMap<String, Object> dynamicMap) {
- if (isAccessToken()) {//是否添加token
- dynamicMap.put("token", TokenManager.getInstance().getToken());
- }
- if (isSign()) {//是否添加签名
- dynamicMap.put("sign", TokenManager.getInstance().getSign());
- }
- if (isTimeStamp()) {//是否添加请求时间戳
- dynamicMap.put("timeStamp", DateUtils.getNowMills());
- }
- return dynamicMap;//dynamicMap:是原有的全局参数+局部参数+新增的动态参数
- }
(2)设置动态参数添加拦截器。
XHttpSDK.addInterceptor(new CustomDynamicInterceptor()); //设置动态参数添加拦截器
当服务端返回一些独特的错误码(一般是token校验错误、失效,请求过于频繁等),需要我们进行全局性的拦截捕获,并作出相应的响应时,我们就需要定义一个特殊的拦截器求处理这些请求。
(1)继承BaseExpiredInterceptor,实现isResponseExpired和responseExpired方法。
(2)设置失效请求校验拦截器。
XHttpSDK.addInterceptor(new CustomExpiredInterceptor()); //请求失效校验拦截器
如果你不想使用默认的ApiResult实体作为统一的服务端响应实体,比如说你想要下面的响应实体:
- private int errorCode; //请求的错误码
- private String errorInfo; //请求错误的原因描述
- private T result; //请求的结果
- private long timeStamp; //服务端返回的时间戳
(1)首先,继承ApiResult实体,重写其getCode、getMsg、isSuccess和getData方法。
(2)进行请求的时候使用execute(CallBackProxy)或者execute(CallClazzProxy方法进行请求
- XHttp.get("/test/testCustomResult")
- .execute(new CallBackProxy<CustomApiResult<Boolean>, Boolean>(new TipRequestCallBack<Boolean>() {
- @Override
- public void onSuccess(Boolean response) throws Throwable {
- ToastUtils.toast("请求成功:" + response);
- }
- }){}); //千万注意,这里的{}一定不能去掉,否则解析错误
【注意】上面提示的{}一定不能去掉,否则解析错误, 会报"ApiResult.class.isAssignableFrom(cls) err!!"的错误。
如果你觉得写一长串比较麻烦,你可以自定义请求继承你需要的请求方式,例如这里是get请求,我们可以这样写:
- public class CustomGetRequest extends GetRequest {
-
- public CustomGetRequest(String url) {
- super(url);
- }
-
- @Override
- public <T> Observable<T> execute(Type type) {
- return execute(new CallClazzProxy<CustomApiResult<T>, T>(type) {
- });
- }
-
- @Override
- public <T> Disposable execute(CallBack<T> callBack) {
- return execute(new CallBackProxy<CustomApiResult<T>, T>(callBack) {
- });
- }
- }

然后我们就可以用自定义的CustomGetRequest进行请求了,是不是简化了很多呢。
- new CustomGetRequest("/test/testCustomResult")
- .execute(new TipRequestCallBack<Boolean>() {
- @Override
- public void onSuccess(Boolean response) throws Throwable {
- ToastUtils.toast("请求成功:" + response);
- }
- });
如果你对retrofit接口情有独钟,我也提供了相应的api方便调用.
1.定义retrofit接口。例如我定义一个用户添加的接口:
- /**
- * 使用的是retrofit的接口定义
- */
- public interface UserService {
- @POST("/user/registerUser/")
- @Headers({"Content-Type: application/json", "Accept: application/json"})
- Observable<ApiResult<Boolean>> registerUser(@Body RequestBody jsonBody);
-
-
- @POST("/user/registerUser/")
- @Headers({"Content-Type: application/json", "Accept: application/json"})
- Observable<ApiResult> register(@Body RequestBody jsonBody);
- }
2.使用XHttp.custom()构建的CustomRequest进行请求,你可以使用apiCall和call进行请求。
registerUser。register。使用示例如下:
- CustomRequest request = XHttp.custom();
- request.apiCall(request.create(TestApi.UserService.class)
- .registerUser(HttpUtils.getJsonRequestBody(UserManager.getInstance().getRandomUser())))
- .subscribeWith(new TipRequestSubscriber<Boolean>() {
- @Override
- protected void onSuccess(Boolean aBoolean) {
- ToastUtils.toast("添加用户成功!");
- }
- });
- CustomRequest request = XHttp.custom();
- request.call(request.create(TestApi.UserService.class)
- .register(HttpUtils.getJsonRequestBody(UserManager.getInstance().getRandomUser())))
- .subscribeWith(new TipRequestSubscriber<ApiResult>() {
- @Override
- protected void onSuccess(ApiResult apiResult) {
- ToastUtils.toast("添加用户成功!");
- showResult(JsonUtil.toJson(apiResult));
- }
- });

目前框架提供了如下8种缓存策略:
对于缓存的实现,提供了磁盘缓存LruDiskCache和内存缓存LruMemoryCache两种实现,默认使用的是磁盘缓存。
(1)可以先进行缓存的全局性配置,配置缓存的有效期、缓存大小,缓存路径、序列化器等。
- XHttp.getInstance()
- .setIsDiskCache(true) //设置使用磁盘缓存
- .setCacheTime(60 * 1000) //设置全局缓存有效期为一分钟
- .setCacheVersion(1) //设置全局缓存的版本
- .setCacheDirectory(Utils.getDiskCacheDir(this, "XHttp")) //设置全局缓存保存的目录路径
- .setCacheMode(CacheMode.NO_CACHE) //设置全局的缓存策略
- .setCacheDiskConverter(new GsonDiskConverter())//默认缓存使用序列化转化
- .setCacheMaxSize(50 * 1024 * 1024);//设置缓存大小为50M
(2)在进行请求的时候,设置缓存模式和缓存的key即可。如下:
- XHttp.get("/book/getAllBook")
- .timeOut(10 * 1000)//测试局部超时10s
- .cacheMode(mCacheMode)
- .cacheKey(CACHE_KEY)//缓存key
- .retryCount(5)//重试次数
- .cacheTime(5 * 60)//缓存时间300s,默认-1永久缓存 okhttp和自定义缓存都起作用
- .cacheDiskConverter(new GsonDiskConverter())//默认使用的是 new SerializableDiskConverter();
- .timeStamp(true)
- .execute(new ProgressLoadingCallBack<CacheResult<List<Book>>>(mIProgressLoader) {
- @Override
- public void onSuccess(CacheResult<List<Book>> cacheResult) {
- ToastUtils.toast("请求成功!");
- String from;
- if (cacheResult.isFromCache) {
- from = "我来自缓存";
- } else {
- from = "我来自远程网络";
- }
- showResult(from + "n" + JsonUtil.toJson(cacheResult.data));
- }
-
- @Override
- public void onError(ApiException e) {
- super.onError(e);
- ToastUtils.toast(e.getDisplayMessage());
- }
- });

- #XHttp2
- -keep class com.xuexiang.xhttp2.model.** { *; }
- -keep class com.xuexiang.xhttp2.cache.model.** { *; }
- -keep class com.xuexiang.xhttp2.cache.stategy.**{*;}
- -keep class com.xuexiang.xhttp2.annotation.** { *; }
-
- #okhttp
- -dontwarn com.squareup.okhttp3.**
- -keep class com.squareup.okhttp3.** { *;}
- -dontwarn okio.**
- -dontwarn javax.annotation.Nullable
- -dontwarn javax.annotation.ParametersAreNonnullByDefault
- -dontwarn javax.annotation.**
-
- # Retrofit
- -dontwarn retrofit2.**
- -keep class retrofit2.** { *; }
- -keepattributes Exceptions
-
- # RxJava RxAndroid
- -dontwarn sun.misc.**
- -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
- long producerIndex;
- long consumerIndex;
- }
- -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
- rx.internal.util.atomic.LinkedQueueNode producerNode;
- }
- -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
- rx.internal.util.atomic.LinkedQueueNode consumerNode;
- }
-
- #如果用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错
- -keepattributes Signature
- -keep class com.google.gson.stream.** { *; }
- -keepattributes EnclosingMethod
- -keep class org.xz_sale.entity.**{*;}
- -keep class com.google.gson.** {*;}
- -keep class com.google.**{*;}
- -keep class sun.misc.Unsafe { *; }
- -keep class com.google.gson.stream.** { *; }
- -keep class com.google.gson.examples.android.model.** { *; }

https://github.com/zhou-you/RxEasyHttp
新手提问前,请先阅读【提问的智慧】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。