由于NoHttpRxUtils是通过RxJava对NoHttp网络框架操作进行一系列封装。
首先对RxJava和NoHttp网络框架做一个简介
RxJava框架是什么?
RxJava是响应式程序设计的一种实现。
在响应式程序设计中,当数据到达的时候,消费者做出响应。
响应式编程可以将事件传递给注册了的observer。
RxJava框架GitHub链接(ReactiveX)
NoHttp框架是什么?
Nohttp是一个专门针对Android网络通讯的框架
Nohttp框架特性
比Retrofit使用更简单、更易用。
动态配置底层框架为OkHttp、HttpURLConnection
支持异步请求、支持同步请求
多文件上传,支持大文件上传,表单提交数据
文件下载、上传下载、上传和下载的进度回调、错误回调
支持Json、xml、Map、List的提交
完美的Http缓存模式,可指定缓存到数据库、SD卡,缓存数据已安全加密
自定义Request,直接请求JsonObject、JavaBean等
Cookie的自动维持,App重启、关开机后还持续维持
http 301 302 303 304 307重定向,支持多层嵌套重定向
Https、自签名网站Https的访问、支持双向验证
失败重试机制,支持请求优先级
GET、POST、PUT、PATCH、HEAD、DELETE、OPTIONS、TRACE等请求协议
用队列保存请求,平均分配多线程的资源,支持多个请求并发
支持取消某个请求、取消指定多个请求、取消所有请求
支持断点续传和断点处继续下载
NoHttp框架GitHub链接(严振杰)
NoHttpRxUtils框架是什么?
NoHttpRxUtils主要是通过RxJava框架对NoHttp网络框架操作进行再次封装。
减轻使用者繁琐的调用,让使用者更专注于项目业务,而非客户端与服务器之间的网络通讯。
由于NoHttpRxUtils网络请求方面是采用NoHttp同步请求,所以请求队列不是NoHttp队列算法而是NoHttpRxUtils队列算法。
暂时不支持队列请求优先级设置。如果要想让一个请求优先,可以使用Rx线程单一请求。
由于Android系统对SD卡写入权限的约束,所以所有的缓存数据路径都指向于数据库。
NoHttpRxUtils框架功能
* 框架初始化、网络请求、文件下载调用方式全采用链式。
* 数据请求方面,支持RxJava线程队列请求和Rx线程单一请求。
* RxJava线程队列请求=>通过算法实现线程池对RxJava框架线程进行管理和操作,支持撤销单个请求、多个请求,指定请求。
* Rx线程单一请求=>直接开启一个RxJava线程,不进行队列优先直接请求。
* 文件下载,下载队列是NoHttp队列算法。针对NoHttp数据下载进行Android-Service捆绑封装,支持单个下载任务取消(暂停)、多个下载任务取消、单个下载任务恢复(开始)、多个下载任务恢复(开始)。
* 支持自动通过指定对象去得到服务器数据。Json格式数据转换层采用Gson框架转换(转换对象中定义的数据结构必须要符合Json数据结构)
* 支持轮询请求,支持撤销单个轮询请求、多个轮询请求、指定轮询请求。
* 支持使用其它网络框架去轮询请求
NoHttpRxUtils框架-RxJava-1版-Github链接(李奇)
NoHttpRxUtils框架-RxJava-2版-Github链接(李奇)
一个框架开始之前是不是应该去初始化呢?
对,没错。现在我就教你NoHttpRxUtils去如何初始化
链式初始化NoHttp,建议放到Application中onCreate生命周期方法里面
//初始化NoHttp(在此处其实可以调用setDialogGetListener设置全局请求加载框)
RxNoHttpUtils.rxNoHttpInit(getApplicationContext())
//是否维护Cookie
.setCookieEnable(false)
//是否缓存进数据库DBCacheStore
.setDbEnable(true)
//是否开启debug调试
.isDebug(true)
//设置debug打印Name
.setDebugName("LiQi-NoHttpUtils")
//设置全局连接超时时间。单位秒,默认30s。
.setConnectTimeout(40)
//设置全局服务器响应超时时间,单位秒,默认30s。
.setReadTimeout(40)
//设置下载线程池并发数量(默认并发数量是3)
.setThreadPoolSize(3)
//设置网络请求队列并发数量(默认并发数量是3)
.setRunRequestSize(4)
//设置全局默认加载对话框 。注:不允许在此方法里面创建dialog对象。
.setDialogGetListener("全局加载框获取接口")
//设置底层用那种方式去请求
.setRxRequestUtilsWhy(NoHttpInit.OKHTTP)
//设置全局带证书安全协议请求(如果在请求调用的时候切换了安全协议方式,允许覆盖此设置)
.setInputStreamSSL(new InputStream())
//设置全局无证书安全协议请求(如果在请求调用的时候切换了安全协议方式,允许覆盖此设置)
.setInputStreamSSL()
//添加全局请求头
.addHeader("app>>head","app_head_global")
//添加全局请求参数-只支持String类型
.addParam("app_param","app_param_global")
//设置Cookie管理监听。
.setCookieStoreListener(new DBCookieStore.CookieStoreListener())
//设置全局主机验证(如果在请求调用的时候切换了无证书安全协议方式,此设置失效)
.setHostnameVerifier(new HostnameVerifier())
//设置全局重试次数,配置后每个请求失败都会重试设置的次数。
.setRetry(5)
//设置全局请求网络出现未知错误提示语
.setAnUnknownErrorHint("全局未知错误提示语")
//开始初始化NoHttp
.startInit()
初始化就是这么简单,就问你惊不惊喜,意不意外。
初始化需要注意的事项:
1:通过setDialogGetListener()设置对话框时候,对话框依赖的context必须是栈顶context
2:当初始化时通过setHostnameVerifier()/设置全局主机验证,但是如果在请求调用的时候切换了无证书安全协议方式,此设置失效。
来来来,我来讲讲如何使用NoHttpRxUtils去数据下载!
下载开启(又是链式调用)
//获取下载请求构建器
NoHttpDownloadUtils.getNoHttpDownloadBuild()
//添加下载文件参数
.addDownloadParameter(DOWNLOAD_FILE01, "Liqi_single_test.apk")
//设置是否断点续传下载
.setRange(true)
//设置下载进度监听接口
.setDownloadListener(this)
//设置在指定的文件夹发现同名的文件是否删除后重新下载
.setDeleteOld(false)
//设置下载文件存储文件路径
.setFileFolder(FILEPATH)
//单个请求设置读取时间(单位秒,默认以全局读取超时时间。)
.setReadTimeout(40)
//单个请求设置链接超时时间(单位秒,默认以全局链接超时时间。)
.setConnectTimeout(40)
//单个请求设置请求失败重试计数。默认值是0,也就是说,失败后不会再次发起请求。
.setRetryCount(3)
//开启下载
.satart(this)
下载暂停(取消)
//暂停全部正在下载任务
NoHttpDownloadUtils.cancelAll();
//暂停指定下载任务
NoHttpDownloadUtils.cancel(downloadUrl);
有暂停,那必须就得有恢复。
//恢复指定下载
NoHttpDownloadUtils.startRequest(downloadUrl);
//恢复全部下载
NoHttpDownloadUtils.startAllRequest();
当你觉得所有连接下载没用了,那么你也是可以全部取消的哦!
//清空当前下载请求对象,并停止服务
NoHttpDownloadUtils.clearAll();
你也可以对下载Url对应的what值进行操作
//获取下载URL对象的What值
NoHttpDownloadUtils.getDownloadRequestsWhat(downloadUrl);
//移除下载URL对应的What
NoHttpDownloadUtils.removeWhatData(downloadUrl);
//移除全部下载What
NoHttpDownloadUtils.removeWhatAll();
下载注意事项:
如果上一次下载任务没有完成或者没有清空,那么下一次点击任何下载都会继续执行上一次没有完成的任务继续下载
这一次讲讲如何使用NoHttpRxUtils去数据请求!
NoHttpRxUtils网络请求(还是链式调用)
//获取请求对象
RxNoHttpUtils.rxNoHttpRequest()
//get请求方式(除了get和post请求,还支持put,delete,head,patch,options,trace)
.get()
//post请求方式(除了get和post请求,还支持put,delete,head,patch,options,trace)
.post()
//设置Url
.url("url")
//添加请求参数
//当传入的参数类型不属于内部设定类型时,默认调用Object的toString()转换为String类型参数
.addParameter()
//添加请求头
.addHeader()
//设置请求bodyEntity为StringEntity,并传请求类型。
.requestStringEntity(Content-Type)
//为StringEntity添加body中String值
.addStringEntityParameter("请求的String")
//从bodyEntity切换到请求配置对象
.transitionToRequest()
//设置请求bodyEntity为JsonObjectEntity.json格式:{"xx":"xxx","yy":"yyy"}
.requestJsonObjectEntity()
//给JsonObjectEntity添加参数和值
.addEntityParameter("key","Valu")
//从bodyEntity切换到请求配置对象
.transitionToRequest()
//设置请求bodyEntity为JsonListEntity.json格式:[{"xx":"xxx"},{"yy":"yyy"}]
.requestJsonListEntity()
//给JsonList创造对象,并传键值参数
.addObjectEntityParameter("key","Valu")
//在创造对象的上添加键值参数
.addEntityParameter("key","Valu")
//把创造对象刷进进JsonList里面
.objectBrushIntoList()
//从bodyEntity切换到请求配置对象
.transitionToRequest()
//设置请求bodyEntity为InputStreamEntity
.requestInputStreamEntity(Content-Type)
//给InputStreamEntity添加输入流
.addEntityInputStreamParameter(InputStream)
//从bodyEntity切换到请求配置对象
.transitionToRequest()
//单个请求设置读取时间(单位秒,默认以全局读取超时时间。)
.setReadTimeout(40)
//单个请求设置链接超时时间(单位秒,默认以全局链接超时时间。)
.setConnectTimeout(30)
//单个请求设置请求失败重试计数。默认值是0,也就是说,失败后不会再次发起请求。
.setRetryCount(3)
//单个请求设置缓存key
.setCacheKey("get请求Key")
//单个请求设置缓存模式(跟原生NoHttp五种缓存模式一致)
.setCacheMode(CacheMode.REQUEST_NETWORK_FAILED_READ_CACHE)
//设置当前请求是否添加进Rx"线程池"队列中(默认是添加rx"线程池"中.!!如果设置false,请求线程不经过Rx"线程池"直接请求)
.setQueue(false)
//设置Rx"线程池"队列标识.(标识设置请保证唯一.!!如果setQueue(false)设置为false,setSign(标识对象)设置无任何作用)
.setSign(new Object())
//添加HTTPS协议无证书参数
.addHttpsIsCertificate()
//添加HTTPS协议有证书参数
.addHttpsIsCertificate(InputStream)
//设置请求图片的最大宽高
.setBitmapMaxWH(500,500)
//设置请求位图的配置和比例
.setBitmapConfigType(Bitmap.Config, ImageView.ScaleType)
//设置请求加载框(如果此处没有设置加载框,那么就默认使用初始化设置的加载框) 。注:不允许在此方法里面创建dialog对象。
.setDialogGetListener(this)
//设置请求网络出现未知错误提示语
.setAnUnknownErrorHint("未知错误提示语")
//创建请求对象,并指定响应转换类型和请求成功或者失败回调接口
.builder(Objects.class,new OnIsRequestListener)
//开始请求
.requestRxNoHttp();
这么"白痴"式的调用,是不是很惊讶!
请求注意事项:
1:BodyEntity内部自动处理的格式只有两种,json格式:{"xx":"xxx","yy":"yyy"}+json格式:[{"xx":"xxx"},{"yy":"yyy"}]。如果这两种格式不满足你的需求,你可以自己把BodyEntity的格式转换字符串传输。
2:如果此方法setQueue(false)赋值为false的话,请求线程不经过Rx"线程池队列"直接请求。并且setSign(new Object())设置的值无效,也不可取消此请求。
3:如果使用addHttpsIsCertificate()HTTPS协议无证书参数,那么设置全局主机验证对这个请求失效
手动取消Rx"线程池"中队列请求(setQueue(false)如果设置为false,手动取消将失去作用)
//单个取消Sign对应的请求
RxNoHttpUtils.cancel(Sign));
//取消批量Sign对应的请求
RxNoHttpUtils.cancel(Sign[]);
//取消RX"线程池"中所有的请求
// RxNoHttpUtils.cancelAll();
一个网络框架怎么能没有轮询呢
来来来,看看NoHttpRxUtils去如何轮询请求的。
NoHttpRxUtils轮询请求,继续采用链式调用
//获取请求对象
RxNoHttpUtils.rxNoHttpRequest()
//NoHttp网络请求设置参数跟上面一样设置
...
//设置当前轮询请求Sign
.setSign(new Object())
//创建轮询请求对象,并指定响应转换类型和请求成功或者失败回调接口
.builderPoll(Objects.class,new OnIsRequestListener)
//设置初始化加载延迟
.setInitialDelay(3 * 1000)
//设置轮询间隔时间-默认3秒
.setPeriod(5 * 1000)
//设置被观察者产生的行为事件监听器-
//(如果此处实现被观察者产生的行为事件监听器,那么框架内部就不去维护此轮询请求,必须实现轮询拦截器接口去维护此轮询什么时候停止。 RxNoHttpUtils.cancelPoll()取消轮询将无效,设置内部加载框将无效 )
.setOnObserverEventListener(new OnObserverEventListener(){
@Override
public RxInformationModel onObserverEvent(RestRequest transferValue) {
// RxInformationModel对象方法介绍
//getData()=获取请求数据
//setData(T data)=赋值请求数据
//setException(boolean exception)=赋值是否是异常状态
//isException()=获取是否异常状态
//setThrowable(Throwable throwable)=赋值异常类
//getThrowable()=获取异常类
//setStop(boolean stop)=赋值是否停止轮询状态
//isStop()=获取是否轮询状态
//RxInformationModel 此对象需要new 出来.
//在此方法中可以换成自己钟意的网络框架去请求,如果设置了网络请求参数,除 了body其它的都能从RestRequest里面取得。
return informationModel;
}
})
// 设置设置数据拦截监听对象
.setBooleanFunc1(new Func1() {
@Override
public Boolean call(RxInformationModel stringRxInformationModel) {
//在此方法里面可以根据RxInformationModel.getData()获取请求的数据,然后根据请求的数据来决定是否停止轮询
return stringRxInformationModel.isStop();
} })
//设置观察者根据被观察产生的行为做出相应处理监听器
//如果实现了此接口,那么builderPoll中实现的OnIsRequestListener将无效。
.setRxInformationModelAction1(new Action1() {
@Override
public void call(RxInformationModel stringRxInformationModel) {
//在此方法里面根据RxInformationModel中的数据做出相应动作
}
})
//转换成轮询请求类
.switchPoll()
//开始请求
.requestRxNoHttp();
轮询请求注意事项:
1:如果想停止轮询请求,可以根据setSign(new Object())设置的值去手动取消轮询请求,也可以根据setBooleanFunc1(new Func1())方法去赋值轮询拦截器,在实现的方法里面可以根据RxInformationModel.getData()获取请求的数据,然后根据请求的数据来决定是否停止轮询
2:如果通过setOnObserverEventListener(new OnObserverEventListener())方法去实现OnObserverEventListener对象,你可以在实现的方法里面换成自己钟意的网络框架去请求,如果设置了网络请求参数,除了body其它的都能从RestRequest里面取得。但是框架内部就不去维护此轮询请求,无法通过框架去停止此轮询请求,必须实现轮询拦截器接口去维护此轮询什么时候停止。
3:如果通过setRxInformationModelAction1(new Action1())方法去赋值Action1,那么builderPoll中实现的OnIsRequestListener将无效。
如何取消轮询请求?
//单个取消Sign对应的轮询请求
RxNoHttpUtils.cancelPoll(Sign));
//取消批量Sign对应的轮询请求
RxNoHttpUtils.cancelPoll(Sign[]);
//取消所有的轮询请求
// RxNoHttpUtils.cancelPollAll();
如果你开启了缓存,那么这里就教你清除缓存
//清除对应的key的缓存数据
RxNoHttpUtils.removeKeyCacheData("Cachekey");
//清除所有缓存数据
RxNoHttpUtils.removeAllCacheData();
下载下来的NohttpRxUtils项目结构
nohttputils是针对Nohttp请求进行封装的工具,sample是调用nohttputils工具的demo。
所有Activity的基类BaseActivity
BaseActivity中实现了两个接口:DialogGetInterfa,RequestOkAndNo
DialogGetInterfa接口:网络请求加载对话框获取接口(nohttputils内部定义的接口,不实现就不弹出加载对话框或者弹出初始化设置的默认加载框)
RequestOkAndNo
接口: 网络请求成功或者失败的接口(nohttputils内部定义的接口)
RequestOkAndNo
onNext(T response):由于返回的参数是泛型,就是代表任何类型都可以返回。!如果想把网络返回的数据装进指定的对象中,那么该对象的定义请按照Gson框架要求去定义。因为数据转换那层,我是使用了Gson框架。(主线程运行)
onError(Throwable e):在nohttputils内部做了一些错误捕捉提示,如还需自己提示的错误,请自己在实现此方法里面diy。(注:如果此网络请求没有设置加载对话框,那么就无法显示nohttputils内置的错误提示)(主线程运行)
其它Activity界面通过继承BaseActivity,实现当前的界面业务和逻辑
当前Activity继承BaseActivity,通过指定当前网络请求成功返回的数据类型。网络请求成功后可以在onNext回调方法里面做自己相应的逻辑和界面控件操作