XDroidRequest网络请求框架,新开源
XDroidRequest 是一款网络请求框架,它的功能也许会适合你。这是本项目的第三版了,前两版由于扩展性问题一直不满意,思考来 思考去还是觉得Google的Volley的扩展性最强,于是借鉴了Volley的责任链模式,所以有了这个第三版.
Provide
1 适配 Android 6.0 ,不再使用HttpClient相关API
2 一行代码发送请求,提供多种回调函数供选择,
3 支持8种网络请求方式 GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH
4 支持请求的优先级设置,优先级高的将先于优先级低的发送请求
5 支持取消请求,可以取消当前已发送的请求(可自定义取消请求的依据条件),也可以取消请求队列中还未发送的请求
6 支持多请求并发,多个请求同时发送,底层使用固定数量线程池,可设置线程池的大小
7 支持重复请求的判断,当有重复的请求将挂起,等待第一个请求完成后,挂起的请求使用已经请求完毕的缓存,如果未开启缓存,则会继续请求网络
8 支持请求失败重试,默认重试2次,重试超时时间会递增,递增速率可设置,默认为1倍递增
9 支持多文件与大文件上传,可以与参数一起发送至服务器,提供上传进度回调
10 支持大文件下载,提供下载进度回调
11 支持发送JSON数据
12 自动网络判定,可设置此时是否显示缓存数据
13 请求结果自动解析,可泛型任何JAVA BEAN,默认实现了GSON解析,可自定义
14 多种错误类型判定
15 扩展性强,可自定义发送请求方式与解析请求结果
16 支持强大的缓存控制
17 支持缓存配置,可配置磁盘缓存路径,磁盘缓存最大值,磁盘缓存当前占有大小,磁盘缓存清理
内存缓存最大值大小,内存缓存清理
18 支持缓存管理与控制,包括本地请求缓存一系列信息查询以及对缓存的手动操作
About cache
1 XDroidRequest使用了二级缓存,内存缓存与磁盘缓存,内存缓存使用LruCache,磁盘缓存使用DiskLruCache
2 setShouldCache(true) ,一个开关控制是否使用缓存的功能
3 setUseCacheDataAnyway(false), 是否总是使用缓存,这个开关开启后,将每次首先从内存和本地查找缓存,有的话直接使用缓存,
请求会在后台执行,完成后会更新缓存。如果没有缓存将直接进行网络请求获取,完成后会更新缓存.
4 setUseCacheDataWhenRequestFailed(true) ,是否在请求失败后使用缓存数据,无网络属于请求失败,可以保证即使没有网络,或者
请求也有数据展示.
5 setUseCacheDataWhenTimeout(true) ,是否在请求超时后直接使用缓存,这里的超时时间并不是网络请求的超时时间,而是我们
设定一个时间,超过这个时间后,不管请求有没有完成都直接使用缓存,后台的请求完成后会自动更新缓存
6 setUseCacheDataWhenUnexpired(true),是否使用缓存当缓存未过期的时候,这个开关也是经常开启的开关,每个缓存都会对应一个过期
时间,先从内存查找缓存,没有的话再从磁盘查找,有缓存且过期的话,将直接使用缓存数据,当过期之后会进行网络请求,请求完成后会更新
内存缓存与磁盘。没有缓存将直接进行网络请求,请求完成后会更新内存与磁盘缓存
7 setRetryWhenRequestFailed(true) ,是否进行重试,当请求失败的时候,默认开启,重试2次,不需要重试功能的话可关闭
8 setNeverExpired(false); 设置缓存是否永不过期
Here is the sample
Download demo.apk
Screenshot
Usage
1.初始化,应用启动的时候进行,主要初始化缓存的路径等信息
XRequest.initXRequest(getApplicationContext());
2.发起请求
① GET请求
/**
* 简单的Get请求
* @param mRequestTag 请求的tag,可根据此tag取消请求
* @param url 请求地址
* @param OnRequestListener 请求结果回调
*/
XRequest.getInstance().sendGet(mRequestTag, url, new OnRequestListenerAdapter<String>() {
@Override
public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
super.onDone(request, headers, result, dataType);
}
});
② POST请求
String url = "http://apis.baidu.com/heweather/weather/free";
RequestParams params = new RequestParams();
params.putHeaders("apikey", "可以到apistore申请");
params.putParams("city", "hefei"); XRequest.getInstance().sendPost(mRequestTag, url, params, new OnRequestListenerAdapter<String>() { @Override
public void onRequestFailed(Request<?> request, HttpException httpException) {
super.onRequestFailed(request, httpException);
switch (httpException.getHttpErrorCode()) {
case HttpError.ERROR_NOT_NETWORK:
Toast.makeText(context, "网络未连接,请检查", Toast.LENGTH_SHORT).show();
break;
}
} @Override
public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
Toast.makeText(context, "获取信息失败,系统已经为您重试" + currentRetryCount+"次", Toast.LENGTH_SHORT).show(); CLog.i("POST请求结果失败,正在重试,当前重试次数:" + currentRetryCount);
} @Override
public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
CLog.i("onRequestDownloadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
} @Override
public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
File currentFile) {
CLog.i("onRequestUploadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
} @Override
public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
super.onDone(request, headers, result, dataType);
}
});
③ 发送JSON字符串参数
RequestParams params = new RequestParams();
params.putParams(
"{\"uid\":863548,\"stickys\":[{\"id\":29058,\"iid\":0,\"content\":\"内容\",\"color\":\"green\",\"createtime\":\"2015-04-16 16:26:17\",\"updatetime\":\"2015-04-16 16:26:17\"}]}");
XRequest.getInstance().sendPost(mRequestTag, url, params, new OnRequestListenerAdapter<String>() {
@Override
public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
super.onDone(request, headers, result, dataType);
}
});
④上传文件
String url = "http://192.168.1.150/upload_multi.php";
RequestParams params = new RequestParams();
params.put("file[0]", new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "app-debug.apk"));
params.put("file[1]", new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "photoview.apk"));
params.putParams("file_name", "上传的文件名称"); XRequest.getInstance().upload(mRequestTag, url, params, new OnRequestListenerAdapter<String>() { @Override
public void onRequestPrepare(Request<?> request) {
Toast.makeText(context, "请求准备", Toast.LENGTH_SHORT).show();
CLog.i("请求准备");
} @Override
public void onRequestFailed(Request<?> request,HttpException httpException) {
Toast.makeText(context, "请求结果失败", Toast.LENGTH_SHORT).show();
CLog.i("请求结果失败");
} @Override
public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
Toast.makeText(context, "获取信息失败,系统已经为您重试" + currentRetryCount+"次", Toast.LENGTH_SHORT).show(); CLog.i("请求结果失败,正在重试,当前重试次数:" + currentRetryCount);
} @Override
public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
File currentFile) {
CLog.i("正在上传第%s个文件,当前进度:%d , 总大小 : %d" ,currentFileIndex,transferredBytesSize,totalSize); mUploadProgressBar.setMax((int) totalSize);
mUploadProgressBar.setProgress((int) transferredBytesSize);
}
@Override
public void onDone(Request<?> request, Map<String, String> headers, String response, DataType dataType) {
Toast.makeText(context, "请求完成", Toast.LENGTH_SHORT).show();
} });
测试了上传百兆以上文件无压力,如果你想测试多文件上传,下面的PHP多文件上传代码供参考。要注意的是PHP默认上传2M以内文件,需要自己改下 配置文件,网上很多,搜索即可
<?php
foreach($_FILES['file']['error'] as $k=>$v)
{
$uploadfile = './upload/'. basename($_FILES['file']['name'][$k]);
if (move_uploaded_file($_FILES['file']['tmp_name'][$k], $uploadfile))
{
echo "File : ", $_FILES['file']['name'][$k] ," is valid, and was successfully uploaded.\n";
} else
{
echo "Possible file : ", $_FILES['file']['name'][$k], " upload attack!\n";
} } echo "成功接收附加字段:". $_POST['file_name']; ?>
⑤下载文件
String url = "http://192.168.1.150/upload/xiaokaxiu.apk";
String downloadPath = "/sdcard/xrequest/download";
String fileName = "test.apk";
XRequest.getInstance().download(mRequestTag, url, downloadPath,fileName, new OnRequestListenerAdapter<File>() {
@Override
public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
CLog.i("正在下载, 当前进度:%d , 总大小 : %d" ,transferredBytesSize,totalSize);
mDownloadProgressBar.setMax((int) totalSize);
mDownloadProgressBar.setProgress((int) transferredBytesSize);
}
@Override
public void onDone(Request<?> request, Map<String, String> headers, File result, DataType dataType) {
CLog.i("下载完成 : %s",result != null?result.toString():"获取File为空");
}
});
⑥关于回调
请求回调OnRequestListener,回调函数很多,根据自己需求选择性复写即可,传入OnRequestListener默认实现类OnRequestListenerAdapter即可
XRequest.getInstance().sendGet(mRequestTag, url, cacheKey, params, new OnRequestListener<String>() { /**
* 请求前准备回调
* 运行线程:主线程
* @param request 当前请求对象
*/
@Override
public void onRequestPrepare(Request<?> request) {
Toast.makeText(context, "GET请求准备", Toast.LENGTH_SHORT).show(); CLog.i("GET请求准备");
} /**
* 请求完成回调
* 运行线程:主线程
* @param request 当前请求对象
* @param headers 请求结果头文件Map集合
* @param result 请求结果泛型对象
*/
@Override
public void onRequestFinish(Request<?> request, Map<String, String> headers, String result) {
Toast.makeText(context, "GET请求结果获取成功", Toast.LENGTH_SHORT).show();
CLog.i("GET请求结果获取成功");
} /**
* 请求失败回调
* 运行线程:主线程
* @param request 当前请求对象
* @param httpException 错误类对象,包含错误码与错误描述
*/
@Override
public void onRequestFailed(Request<?> request, HttpException httpException) {
Toast.makeText(context, "GET请求结果失败", Toast.LENGTH_SHORT).show();
CLog.i("GET请求结果失败");
} /**
* 请求失败重试回调
* 运行线程:主线程
* @param request 当前请求对象
* @param currentRetryCount 当前重试次数
* @param previousError 上一个错误类对象,包含错误码与错误描述
*/
@Override
public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
Toast.makeText(context, "获取信息失败,系统已经为您重试" + currentRetryCount+"次", Toast.LENGTH_SHORT).show(); CLog.i("GET请求结果失败,正在重试,当前重试次数:" + currentRetryCount);
} /**
* 下载进度回调
* 运行线程:子线程
* @param request 当前请求对象
* @param transferredBytesSize 当前下载大小
* @param totalSize 总大小
*
*/
@Override
public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
CLog.i("onRequestDownloadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
} /**
* 上传进度回调
* 运行线程:子线程
* @param request 当前请求对象
* @param transferredBytesSize 当前写入进度
* @param totalSize 总进度
* @param currentFileIndex 当前正在上传的是第几个文件
* @param currentFile 当前正在上传的文件对象
*
*/
@Override
public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
File currentFile) {
CLog.i("onRequestUploadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
} /**
* 缓存数据加载完成回调
* 运行线程:主线程
* @param request 当前请求对象
* @param headers 缓存的头信息Map集合
* @param result 缓存的数据结果对象
*/
@Override
public void onCacheDataLoadFinish(Request<?> request, Map<String, String> headers, String result) {
Toast.makeText(context, "GET请求缓存加载成功", Toast.LENGTH_SHORT).show();
CLog.i("GET请求缓存加载成功");
} /**
* 解析网络数据回调,请求完成后,如果需要做耗时操作(比如写入数据库)可在此回调中进行,不会阻塞UI
* 运行线程:子线程
* @param request 当前请求对象
* @param networkResponse 网络请求结果对象,包含byte数据流与头信息等
* @param result 解析byte数据流构建的对象
*/
@Override
public void onParseNetworkResponse(Request<?> request, NetworkResponse networkResponse, String result) {
CLog.i("GET请求网络数据解析完成");
} /**
* 此请求最终完成回调,每次请求只会调用一次,无论此请求走的缓存数据还是网络数据,最后交付的结果走此回调
* 运行线程:主线程
* @param request 当前请求对象
* @param headers 最终交付数据的头信息
* @param result 最终交付的请求结果对象
* @param dataType 最终交付的数据类型枚举,网络数据/缓存数据
*/
@Override
public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
Toast.makeText(context, "GET请求完成", Toast.LENGTH_SHORT).show();
} });
下面是选择性复写回调函数
String url = "http://apis.baidu.com/heweather/weather/free";
RequestParams params = new RequestParams();
params.putHeaders("apikey", "可以到apistore申请");
params.putParams("city", "hefei"); String cacheKey = url + "post"; //与GET请求的URL一样,为了避免同样的缓存key、这里重新指定缓存key
XRequest.getInstance().sendPost(mRequestTag, url, cacheKey, params, new OnRequestListenerAdapter<String>() { @Override
public void onRequestFailed(Request<?> request, HttpException httpException) {
super.onRequestFailed(request, httpException);
switch (httpException.getHttpErrorCode()) {
case HttpError.ERROR_NOT_NETWORK:
Toast.makeText(context, "网络未连接,请检查", Toast.LENGTH_SHORT).show();
break;
}
} @Override
public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
Toast.makeText(context, "获取信息失败,系统已经为您重试" + currentRetryCount+"次", Toast.LENGTH_SHORT).show(); CLog.i("POST请求结果失败,正在重试,当前重试次数:" + currentRetryCount);
} @Override
public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
CLog.i("onRequestDownloadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
} @Override
public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
File currentFile) {
CLog.i("onRequestUploadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
} @Override
public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
super.onDone(request, headers, result, dataType);
}
}); }
⑦自动解析
String url = "http://apis.baidu.com/apistore/aqiservice/citylist";
RequestParams params = new RequestParams();
params.putHeaders("apikey", "可以到apistore申请");
XRequest.getInstance().sendPost(mRequestTag, url, params, CityRootBean.class, new OnRequestListenerAdapter<CityRootBean<CityBean>>() { @Override
public void onDone(Request<?> request, Map<String, String> headers, CityRootBean<CityBean> result,
DataType dataType) {
CLog.i("Bean信息:" + (result == null ? "null" : result.toString()));
}
});
⑧缓存配置
(1)初始化的时候如果想要指定缓存路径,大小等信息,可参照如下代码
public class App extends Application { @Override
public void onCreate() {
super.onCreate(); configXReqeustCache(); } @SuppressLint("SdCardPath")
private void configXReqeustCache() {
//磁盘缓存路径
File DISK_CACHE_DIR_PATH = new File("/sdcard/xrequest/diskcache");
//磁盘缓存最大值
int DISK_CACHE_MAX_SIZE = 30*1024*1024; //XRequest.initXRequest(getApplicationContext()); XRequest.initXRequest(getApplicationContext(), DISK_CACHE_MAX_SIZE, DISK_CACHE_DIR_PATH);
}
}
(2)查找当前缓存数据占用的空间
long diskCacheCurrentSize = RequestCacheManager.getInstance().getAllDiskCacheSize();
(3)查找缓存路径
String diskCacheDir = RequestCacheManager.getInstance().getDiskCacheDirectory().getPath();
(4)查询当前缓存最大值
long diskCacheMaxSize = RequestCacheManager.getInstance().getDiskCacheMaxSize();
(5)清除所有缓存
RequestCacheManager.getInstance().deleteAllDiskCacheData();
⑨请求配置
在发送请求的时候,有的重载函数需要传入一个RequestCacheConfig对象,不需要传入此对象的重载函数内部传入的是默认的 RequestCacheConfig对象,通过RequestCacheConfig对象控制缓存于网络数据等,下面是默认的RequestCacheConfig配置
public static RequestCacheConfig buildDefaultCacheConfig() {
RequestCacheConfig cacheConfig=new RequestCacheConfig();
cacheConfig.setShouldCache(true); //开启缓存
cacheConfig.setUseCacheDataAnyway(false); //关闭总是优先使用缓存
cacheConfig.setUseCacheDataWhenRequestFailed(true); //开启请求失败使用缓存
cacheConfig.setUseCacheDataWhenTimeout(false); //关闭超时使用缓存
cacheConfig.setUseCacheDataWhenUnexpired(true); //开启当缓存未过期时使用缓存
cacheConfig.setRetryWhenRequestFailed(true); //开启请求失败重试
cacheConfig.setNeverExpired(false); //关闭缓存永不过期 TimeController timeController=new TimeController();
timeController.setExpirationTime(DEFAULT_EXPIRATION_TIME); //设置缓存的过期时间
timeController.setTimeout(DEFAULT_TIMEOUT); //设置缓存超时时间,对应“setUseCacheDataWhenTimeout”函数的超时时间
cacheConfig.setTimeController(timeController); //把时间控制器设置给RequestCacheConfig return cacheConfig;
}
每次请求如果需要重新指定配置,自己构造这样一个对象传入即可
⑩原始发送请求方式
XRequest其实是使用装饰者模式,对一系列请求步骤进行了封装,目的是为了更简单的使用,如果有复杂的需求,需要更高的自由度的话, 可以参考如下发送请求代码
MultipartGsonRequest<Bean> request = new MultipartGsonRequest<T>(cacheConfig, url, cacheKey, Bean.class, onRequestListener);
request.setRequestParams(params);
request.setHttpMethod(HttpMethod.POST);
request.setTag(tag); XRequest.getInstance().addToRequestQueue(request);
XDroidRequest网络请求框架,新开源的更多相关文章
- Android网络请求框架
本篇主要介绍一下Android中经常用到的网络请求框架: 客户端网络请求,就是客户端发起网络请求,经过网络框架的特殊处理,让后将请求发送的服务器,服务器根据 请求的参数,返回客户端需要的数据,经过网络 ...
- Android 网络请求框架android-async-http问题
今天通过接口请求服务器的一些app数据,发现一个很奇怪的问题,请求一个链接的时候,通常在第一次请求发起的时候没有什么问题,能很快的拿到数据,但是 往后再去请求的时候就会等待很久,而且最后会请求失败,一 ...
- 基于Retrofit+RxJava的Android分层网络请求框架
目前已经有不少Android客户端在使用Retrofit+RxJava实现网络请求了,相比于xUtils,Volley等网络访问框架,其具有网络访问效率高(基于OkHttp).内存占用少.代码量小以及 ...
- Volley网络请求框架的基本用法
备注: 本笔记是参照了 http://blog.csdn.net/ysh06201418/article/details/46443235 学习之后写下的 简介: Volley是google官网退 ...
- Android网络请求框架AsyncHttpClient实例详解(配合JSON解析调用接口)
最近做项目要求使用到网络,想来想去选择了AsyncHttpClient框架开进行APP开发.在这里把我工作期间遇到的问题以及对AsyncHttpClient的使用经验做出相应总结,希望能对您的学习有所 ...
- App 组件化/模块化之路——如何封装网络请求框架
App 组件化/模块化之路——如何封装网络请求框架 在 App 开发中网络请求是每个开发者必备的开发库,也出现了许多优秀开源的网络请求库.例如 okhttp retrofit android-asyn ...
- 一步步搭建Retrofit+RxJava+MVP网络请求框架(二),个人认为这次封装比较强大了
在前面已经初步封装了一个MVP的网络请求框架,那只是个雏形,还有很多功能不完善,现在进一步进行封装.添加了网络请求时的等待框,retrofit中添加了日志打印拦截器,添加了token拦截器,并且对Da ...
- C#反射の一个泛型反射实现的网络请求框架
点击下载源码 C#反射の反射详解(点击跳转)C#反射の反射接口(点击跳转)C#反射反射泛型接口(点击跳转)C#反射の一个泛型反射实现的网络请求框架(点击跳转)
- 网络请求框架---Volley
去年的Google I/O大会为android开发者带来了一个网络请求框架,它的名字叫做Volley.Volley诞生的使命就是让Android的网络请求更快,更健壮,而且它的网络通信的实现是基于Ht ...
随机推荐
- SVN的使用、分支合并及解决冲突详解
一.什么是SVN SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS. 二.SVN的下载安装 下载地址:http ...
- ioctl socket getsockopt
一 ioctl 函数产生原因: 虽然在文件操作结构体"struct file_operations"中有很多对应的设备操作函数,但是有些命令是实在找不到对应的操作函数.如CD-RO ...
- 洛谷P2097 资料分发1 题解
题目传送门 这道题竟然是橙色的: 因为可以用并查集来做,当然您用dfs也可以,不过应该要加优化. 一开始就把读入的合并起来,最后逐个查找就好啦... #include<bits/stdc++.h ...
- <<Javascript Patterns>>阅读笔记 -- 第2章 基本技巧(一)
第一次写这种东西, 有些生涩和蹩脚, 也是为了自己在表达或是总结方面有所提高, 同时为看过的东西留个痕迹, 以便日后查阅. 有错误或是不妥的地方, 还望各位指正, 谢谢! 第1章 简介 本章主要介绍了 ...
- CentOS下Redis安装与配置
本文详细介绍redis单机单实例安装与配置,服务及开机自启动.如有不对的地方,欢迎大家拍砖o(∩_∩)o (以下配置基于CentOS release 6.5 Final, redis版本3.0.2 [ ...
- java自定义类
引用数据类型(类) 引用数据类型分类 提到引用数据类型(类),其实我们对它并不陌生,之前使用过的Scanner类.Random类. 我们可以把类的类型为两种: 第一种,Java为我们提供好的类,如Sc ...
- HDU 6060 RXD and dividing(dfs 思维)
RXD and dividing Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Other ...
- Node.js后台开发初体验
Node.js是什么 Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质时对Chrome V8引擎进行了封装 Node.js安装 ...
- linux——(4)磁盘与文件系统管理
概念一:linux-ext2文件系统 ext2在分区的时候会分成多个组块(block group)和一个启动扇区(boot sector),每一个组块内又有superblock.File system ...
- 缩略图信息提取工具vinetto
缩略图信息提取工具vinetto 在Windows操作系统中,为了方便用户快速浏览图片,系统会自动为每个图片生成预览图.预览图默认保存在同目录的Thumbs.db文件中.当图片文件删除后,Thum ...