XHttp2

一个功能强悍的网络请求库,使用RxJava2 + Retrofit2 + OKHttp组合进行封装。还不赶紧点击使用说明文档,体验一下吧!

项目地址

关于我

https://github.com/xuexiangjys

特征

  • 支持默认、全局、局部三个层次的配置功能。
  • 支持动态配置和自定义底层框架Okhttpclient、Retrofit.
  • 加入基础ApiService,减少Api冗余。
  • 支持多种方式访问网络GET、POST、PUT、DELETE等请求协议。
  • 支持网络缓存,六种缓存策略可选,涵盖大多数业务场景。
  • 支持固定添加header和动态添加header。
  • 支持添加全局参数和动态添加局部参数。
  • 支持文件下载、多文件上传和表单提交数据。
  • 支持文件请求、上传、下载的进度回调、错误回调,也可以自定义回调。
  • 支持任意数据结构的自动解析。
  • 支持添加动态参数例如timeStamp时间戳、token、签名sign。
  • 支持自定义的扩展API。
  • 支持多个请求合并。
  • 支持Cookie管理。
  • 支持异步、同步请求。
  • 支持Https、自签名网站Https的访问、双向验证。
  • 支持失败重试机制,可以指定重试次数、重试间隔时间。
  • 支持根据key删除网络缓存和清空网络缓存。
  • 提供默认的标准ApiResult(遵循OpenApi格式)解析和回调,并且可自定义ApiResult。
  • 支持取消数据请求,取消订阅,带有对话框的请求不需要手动取消请求,对话框消失会自动取消请求。
  • 支持请求数据结果采用回调和订阅两种方式。
  • 提供"默认API"、"接口协议"以及"统一请求实体"三种方式进行网络请求,支持自定义网络请求协议。
  • 返回结果和异常统一处理,支持自定义异常处理。
  • 结合RxJava,线程切换灵活。
  • 请求实体支持注解配置,配置网络请求接口的url、是否需要验证token以及请求参数的key。
  • 拥有统一的网络请求取消机制。

1、演示(请star支持)

1.1、Demo演示动画

1.2、Demo下载

1.3、api服务安装

服务端的搭建详细请点击查看

2、如何使用

目前支持主流开发工具AndroidStudio的使用,直接配置build.gradle,增加依赖即可.

2.1、Android Studio导入方法,添加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":{} //返回的数据对象
}

约定了其中CodeMsgData首字母必须大写,否则无法解析成功。

需要自定义返回的实体API请点击查看

1、使用XHttp默认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一般有如下两种方式:

  • execute(CallBack callBack): 直接回调结果。
  • execute(Class clazz)和execute(Type type): 回调Observable对象,可通过订阅获取到结果。

4.请求使用演示

XHttp.get("/user/getAllUser").syncRequest(false) //异步请求.onMainThread(true) //回到主线程.execute(new SimpleCallBack<List<User>>() {@Overridepublic void onSuccess(List<User> response) {refreshLayout.finishRefresh(true);if (response != null && response.size() > 0) {mUserAdapter.refresh(response);mLlStateful.showContent();} else {mLlStateful.showEmpty();}}@Overridepublic 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>() {@Overrideprotected void onSuccess(Boolean aBoolean) {ToastUtils.toast("删除成功!");setFragmentResult(RESULT_OK, null);popToBack();}});


2、使用XHttpRequest封装的统一请求实体进行请求【仅支持post请求】

在使用它之前,需要下载/定义对应的实体协议,如下:

@RequestParams(url = "/user/addUser", accessToken = false)
public static class UserService_AddUser extends XHttpRequest {/****/public User request;@Overrideprotected Boolean getResponseEntityType() {return null;}
}

1.注解说明

  • @RequestParams

注解参数 | 类型 | 默认值 | 备注 :-|:-:|:-:|:- baseUrl | String | "" | 设置该请求的baseUrl url | String | "" | 请求网络接口地址 timeout | long | 15000 | 设置超时时间 accessToken | boolean | true | 设置是否需要验证token cacheMode | CacheMode | CacheMode.NO_CACHE | 设置请求的缓存模式

  • @ParamKey

注解参数 | 类型 | 默认值 | 备注 :-|:-:|:-:|:- key | String | / | 请求参数的key

2.使用XHttpSDK进行请求。

  • post(XHttpRequest xHttpRequest, boolean isSyncRequest, boolean toMainThread): 获取PostRequest请求(使用实体参数名作为请求Key)。
  • postToMain(XHttpRequest xHttpRequest): 获取PostRequest请求(主线程->主线程)。
  • postToIO(XHttpRequest xHttpRequest): 获取PostRequest请求(主线程->子线程)。
  • postInThread(XHttpRequest xHttpRequest): 获取PostRequest请求(子线程->子线程)。
  • execute(XHttpRequest xHttpRequest, boolean isSyncRequest, boolean toMainThread) : 执行PostRequest请求,返回observable对象(使用实体参数名作为请求Key)。
  • 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) {@Overridepublic void onSuccess(Boolean aBoolean) {ToastUtils.toast("用户添加成功!");mRefreshLayout.autoRefresh();}
});


3、使用XHttpProxy代理进行请求【仅支持post请求】

在使用它之前,需要下载/定义对应的接口协议,如下:

/*** 订单*/
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.注解说明

  • @NetMethod

注解参数 | 类型 | 默认值 | 备注 :-|:-:|:-:|:- 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

  • TO_MAIN: executeToMain(main -> io -> main)

【注意】请确保网络请求在主线程中【实质是异步请求(切换到io线程),且响应的线程又切换至主线程】

  • TO_IO: executeToIO(main -> io -> io)

【注意】请确保网络请求在主线程中【实质是异步请求(切换到io线程),不过响应的线程不变,还是之前请求的那个io线程】

  • IN_THREAD: executeInThread(io -> io -> io)

【注意】请确保网络请求在子线程中才可以使用该类型【实质是不做任何线程调度的同步请求】

3.请求使用演示。

//使用XHttpProxy进行接口代理请求
XHttpProxy.proxy(TestApi.IOrder.class).buyBook(mBookAdapter.getItem(position).getBookId(), UserManager.getInstance().getUser().getUserId(), 1).subscribeWith(new TipRequestSubscriber<Boolean>() {@Overridepublic void onSuccess(Boolean aBoolean) {ToastUtils.toast("图书购买" + (aBoolean ? "成功" : "失败") + "!");mRefreshLayout.autoRefresh();}});


4、文件上传和下载

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() {@Overridepublic void onResponseProgress(long bytesWritten, long contentLength, boolean done) {}}).execute(Boolean.class).compose(RxLifecycle.with(this).<Boolean>bindToLifecycle()).subscribeWith(new ProgressLoadingSubscriber<Boolean>(mIProgressLoader) {@Overridepublic 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>() {@Overridepublic void onStart() {HProgressDialogUtils.showHorizontalProgressDialog(getContext(), "图片下载中...", true);}@Overridepublic void onError(ApiException e) {ToastUtils.toast(e.getMessage());HProgressDialogUtils.cancel();}@Overridepublic void update(long bytesRead, long contentLength, boolean done) {HProgressDialogUtils.onLoading(contentLength, bytesRead); //更新进度条}@Overridepublic 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) {@Overridepublic 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种打印模式

  • NONE: 不打印log
  • BASIC: 只打印"请求首行"和"响应首行"。
  • HEADERS: 打印请求和响应的所有 Header
  • PARAM: 只打印请求和响应参数
  • BODY: 打印所有数据(默认是这种)

(2)如果需要对网络请求的相关参数进行自定义记录的话,可以继承HttpLoggingInterceptor实现一个自己的网络请求日志拦截器,重写logForRequestlogForResponse两个方法即可。

(3)设置自定义的日志拦截器.

XHttpSDK.debug(new CustomLoggingInterceptor());

动态参数添加拦截器

有时候,我们需要对所有请求添加一些固定的请求参数,但是这些参数的值又是变化的,这个时候我们就需要动态添加请求参数【例如,请求的token、时间戳以及签名等】

(1)继承BaseDynamicInterceptor,实现updateDynamicParams方法,如下:

@Override
protected TreeMap<String, Object> updateDynamicParams(TreeMap<String, Object> dynamicMap) {if (isAccessToken()) {//是否添加tokendynamicMap.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,实现isResponseExpiredresponseExpired方法。

(2)设置失效请求校验拦截器。

XHttpSDK.addInterceptor(new CustomExpiredInterceptor()); //请求失效校验拦截器

自定义API请求

自定义请求响应的API结构

如果你不想使用默认的ApiResult实体作为统一的服务端响应实体,比如说你想要下面的响应实体:

private int errorCode; //请求的错误码
private String errorInfo; //请求错误的原因描述
private T result; //请求的结果
private long timeStamp; //服务端返回的时间戳

(1)首先,继承ApiResult实体,重写其getCodegetMsgisSuccessgetData方法。

(2)进行请求的时候使用execute(CallBackProxy)或者execute(CallClazzProxy方法进行请求

XHttp.get("/test/testCustomResult").execute(new CallBackProxy<CustomApiResult<Boolean>, Boolean>(new TipRequestCallBack<Boolean>() {@Overridepublic 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);}@Overridepublic <T> Observable<T> execute(Type type) {return execute(new CallClazzProxy<CustomApiResult<T>, T>(type) {});}@Overridepublic <T> Disposable execute(CallBack<T> callBack) {return execute(new CallBackProxy<CustomApiResult<T>, T>(callBack) {});}
}

然后我们就可以用自定义的CustomGetRequest进行请求了,是不是简化了很多呢。

new CustomGetRequest("/test/testCustomResult").execute(new TipRequestCallBack<Boolean>() {@Overridepublic void onSuccess(Boolean response) throws Throwable {ToastUtils.toast("请求成功:" + response);}});

使用自定义的retrofit接口

如果你对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进行请求,你可以使用apiCallcall进行请求。

  • apiCall: 针对的是retrofit定义的接口,返回的是Observable>的情况。对于上面定义的第一个接口registerUser
  • call: 针对的是retrofit定义的接口,返回的是Observable的情况。对于上面定义的第二个接口register

使用示例如下:

CustomRequest request = XHttp.custom();
request.apiCall(request.create(TestApi.UserService.class).registerUser(HttpUtils.getJsonRequestBody(UserManager.getInstance().getRandomUser()))).subscribeWith(new TipRequestSubscriber<Boolean>() {@Overrideprotected 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>() {@Overrideprotected void onSuccess(ApiResult apiResult) {ToastUtils.toast("添加用户成功!");showResult(JsonUtil.toJson(apiResult));}});

缓存策略

目前框架提供了如下8种缓存策略:

  • NO_CACHE: 不使用缓存(默认方式)
  • DEFAULT: 完全按照HTTP协议的默认缓存规则,走OKhttp的Cache缓存
  • FIRST_REMOTE: 先请求网络,请求网络失败后再加载缓存
  • FIRST_CACHE: 先加载缓存,缓存没有再去请求网络
  • ONLY_REMOTE: 仅加载网络,但数据依然会被缓存
  • ONLY_CACHE: 只读取缓存
  • CACHE_REMOTE: 先使用缓存,不管是否存在,仍然请求网络,会回调两次
  • CACHE_REMOTE_DISTINCT: 先使用缓存,不管是否存在,仍然请求网络,会先把缓存回调给你,等网络请求回来发现数据是一样的就不会再返回,否则再返回(这样做的目的是防止数据是一样的你也需要刷新界面)

对于缓存的实现,提供了磁盘缓存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) {@Overridepublic void onSuccess(CacheResult<List<Book>> cacheResult) {ToastUtils.toast("请求成功!");String from;if (cacheResult.isFromCache) {from = "我来自缓存";} else {from = "我来自远程网络";}showResult(from + "n" + JsonUtil.toJson(cacheResult.data));}@Overridepublic 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

联系方式

新手提问前,请先阅读【提问的智慧】

android post请求添加公共参数_XHttp2 一个功能强悍的网络请求库相关推荐

  1. Okhttp 拦截器 请求添加公共参数、公共Headers 方法

    retrofit 基于okhttp.使用retrofit /okhttp时候,这些都会wifi 直连的,不走系统的wifi设置,代理是抓不到包的.所以如果 想抓包那么抓网卡吧,打印请求或者添加公共参数 ...

  2. android post请求添加公共参数_Java实现通用的Get和Post请求组件

    开发中经常遇到发送一个远程请求并解析返回结果的情况,那可以在项目中写一个Get/Post的组件,以后遇到远程请求直接调用即可 实现步骤为: 1.创建一个URL(java.net.URL)对象 2.打开 ...

  3. android retrofit 2.0公共参数,Retrofit2.0 添加公共参数

    //这里可以添加公共参数 Interceptor addQueryParameterInterceptor = new Interceptor() { @Override public Respons ...

  4. Android RxJava操作符的学习---功能性操作符--(有条件)网络请求轮询(结合Retrofit)

    1. 需求场景 2. 功能说明 采用Get方法对 金山词霸API 按规定时间重复发送网络请求,从而模拟 轮询 需求实现 停止轮询的条件 = 当轮询到第4次时 采用 Gson 进行数据解析 3. 具体实 ...

  5. android retrofit 2.0公共参数,Android Retrofit 2.0 使用-补充篇

    之前分享的Android Retrofit 2.0 使用,属于基本的使用,实际开发还远远不够,因此对其补充,主要在Retrofit配置和接口参数. Retrofit配置 添加依赖 app/build. ...

  6. GalHttprequest类库简介——android平台上的一个轻量级的http网络请求及缓存框架

    2019独角兽企业重金招聘Python工程师标准>>> GalHttprequest名字的由来 开发过iOS项目的朋友都应该知道 ASIHTTPRequest类库, ASIHTTPR ...

  7. 在Android系统中添加组合键快捷启动功能

    启动系统特定功能的组合键的判断应该在系统分发按键消息前处理, 这样从系统运行 的角度来说成本最低. 添加组合键处理需要先搞清楚按键消息在framework中采集 和分发子系统的工作流程, 虽然有and ...

  8. android mvp模式例子_Android开发中的MVP模式概念以及网络请求实现顺序

    MVP模式 三层 1.view 2.presenter 3.model View 1.view职责,继承view接口,实现方法,持有presenter,this传入presenter Presente ...

  9. 发布一个开源的c++网络事件库【转载Zark@cppthinker.com】

    Chaos是一个基于Linux平台, reactor模式的网络事件库, 目前仅支持TCP传输协议, 仅在x86_64下编译, 并遵循3-clause BSD开源协议. 在使用上, 可以说它很像boos ...

最新文章

  1. 数字图像处理:(5)非微分算子在数字图像处理中的应用
  2. maven项目中 把依赖的jar包一起打包
  3. python尝试不同的随机数进行数据划分、使用卡方检验依次计算不同随机数划分下训练接和测试集所有分类特征的卡方检验的p值,如果所有p值都大于0.05则训练集和测试集都具有统计显著性、数据划分合理
  4. python装饰器实例-Python装饰器实用例子
  5. zebra打印机注意点
  6. MySQL exists的用法介绍
  7. [BZOJ 3894]文理分科(最小割)
  8. setitimer 创建两个定时器_UE4 Timer(定时器)相关源码分析
  9. 连接linux工具有哪些_推荐 10 个不错的网络监视工具,值得收藏
  10. Rails运行时sqlite3报错问题的解决
  11. mysql 1053错误,无法启动的解决方法
  12. Java 性能优化系列之3.1[JVM调优]
  13. L298N电机驱动原理图+PCB制版文件(和你买的模块一模一样的!)
  14. 快播案:程序正义、盗版和色情
  15. oracle 范鑫_20集 JAVA数据库连接视频教程 JAVA能力提升专题视频教程 JDBC动力节点视频教程,全套视频教程学习资料通过百度云网盘下载...
  16. 关于 IE 浏览器打开时速度过慢的问题
  17. 如何系统磁盘和raid卡的槽位对应起来
  18. VMware网络NAT模式无法连接解决方法
  19. web自动化断言_无需断言即可进行Web开发的自动化测试
  20. 人一生必看的100部电影(全球最佳电影排名榜TOP250)

热门文章

  1. PHP7.3中fileinfo怎么安装与开启
  2. Docker核心技术之Docker Compose
  3. MinGW-w64 编译器下载,安装,以及环境变量配置
  4. spring 组件基于注解的注册方式
  5. 浅谈UWB(超宽带)室内定位技术(转载)
  6. tomcat的webapps下没有出现配置过的文件夹
  7. 洛谷 P1411 树
  8. 20145236《网络攻防》Exp4 恶意代码分析
  9. 0 - python简介
  10. Linux上用户执行命令记录