上篇文章,我们讲解了xUtils的注解、图片加载以及数据库操作,如果你未了解,请先查看xUtils使用详解(一)。今天就来看看xUtils的另一主要功能,网络模块!
HttpUtils模块。
(1).支持同步,异步方式的请求; (2).支持大文件上传,上传大文件不会oom; (3).支持GET,POST,PUT,MOVE,COPY,DELETE,HEAD,OPTIONS,TRACE,CONNECT请求; (4).下载支持301/302重定向,支持设置是否根据Content-Disposition重命名下载的文件; (5).返回文本内容的请求(默认只启用了GET请求)支持缓存,可设置默认过期时间和针对当前请求的过期时间。
1.get请求。
首先需要介绍RequestParams类。
RequestParams 是网络请求参数实体,负责将网络请求中的各种数据组装。它提供了好几种构造方法,其中比较常用的是RequestParams(String uri)方法,参数是请求地址,
/** * @param uri 不可为空 */ public RequestParams(String uri) { this(uri, null, null, null); }
它的内部其实还是调用了它的RequestParams(String uri, ParamsBuilder builder, String[] signs, String[] cacheKeys)方法,
/** * @param uri 不可为空 * @param builder * @param signs * @param cacheKeys */ public RequestParams(String uri, ParamsBuilder builder, String[] signs, String[] cacheKeys) { if (uri != null && builder == null) { builder = new DefaultParamsBuilder(); } this.uri = uri; this.signs = signs; this.cacheKeys = cacheKeys; this.builder = builder; }
它提供了好几种添加参数的方法,
(1).addQueryStringParameter(String name, String value) 添加参数至URL中,用于GET请求。
/** * 添加参数至Query String * * @param name * @param value */ public void addQueryStringParameter(String name, String value) { if (!TextUtils.isEmpty(name)) { this.queryStringParams.add(new KeyValue(name, value)); } }
(2).addBodyParameter(String name, String value) 添加参数至body中,只有POST, PUT, PATCH, DELETE请求支持。
/** * 添加参数至Body * * @param name * @param value */ public void addBodyParameter(String name, String value) { if (!TextUtils.isEmpty(name)) { this.bodyParams.add(new KeyValue(name, value)); } else { this.bodyContent = value; } }
(3).addBodyParameter(String name, File value) 用于上传文件。
/** * 添加body参数 */ public void addBodyParameter(String name, File value) { addBodyParameter(name, value, null, null); }
(4).addParameter(String name, Object value) 根据请求方法不同,会将参数添加到不同的地方。例如GET请求,添加参数至URL中;而POST, PUT, PATCH, DELETE请求,则将参数添加至body中。
/** * 添加请求参数(根据请求谓词, 将参数加入QueryString或Body.) * * @param name 参数名 * @param value 可以是String, File, InputStream 或 byte[] */ public void addParameter(String name, Object value) { if (value == null) return; if (method == null || HttpMethod.permitsRequestBody(method)) { if (!TextUtils.isEmpty(name)) { if (value instanceof File || value instanceof InputStream || value instanceof byte[]) { this.fileParams.add(new KeyValue(name, value)); } else { if (value instanceof Iterable) { for (Object item : (Iterable) value) { this.bodyParams.add(new ArrayItem(name, item)); } } else if (value instanceof JSONArray) { JSONArray array = (JSONArray) value; int len = array.length(); for (int i = 0; i < len; i++) { this.bodyParams.add(new ArrayItem(name, array.opt(i))); } } else if (value.getClass().isArray()) { int len = Array.getLength(value); for (int i = 0; i < len; i++) { this.bodyParams.add(new ArrayItem(name, Array.get(value, i))); } } else { this.bodyParams.add(new KeyValue(name, value)); } } } else { this.bodyContent = value.toString(); } } else { if (!TextUtils.isEmpty(name)) { if (value instanceof Iterable) { for (Object item : (Iterable) value) { this.queryStringParams.add(new ArrayItem(name, item)); } } else if (value.getClass().isArray()) { int len = Array.getLength(value); for (int i = 0; i < len; i++) { this.queryStringParams.add(new ArrayItem(name, Array.get(value, i))); } } else { this.queryStringParams.add(new KeyValue(name, value)); } } } }
下面给出一个请求事例,代码如下,
RequestParams params = new RequestParams(url); params.addQueryStringParameter("username","abc");//设置参数 params.addQueryStringParameter("password","123");//设置参数 x.http().get(params, new Callback.CommonCallback() { @Override public void onSuccess(String result) { } //请求异常后的回调方法 @Override public void onError(Throwable ex, boolean isOnCallback) { } //主动调用取消请求的回调方法 @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } });
2.post请求。
例如代码如下,
RequestParams params = new RequestParams(url); params.addBodyParameter("username","zxw");//设置参数 params.addParameter("password","123456");//设置参数 params.addHeader("head","android"); //添加一个请求头 x.http().post(params, new Callback.CommonCallback() { @Override public void onSuccess(String result) { } @Override public void onError(Throwable ex, boolean isOnCallback) { } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } });
xUtils已经封装了GET请求和POST请求。如果还需要其他请求方式,那么该怎么操作呢?
3.其他请求方式。
使用案例代码如下,
RequestParams params = new RequestParams(url); params.addParameter("username","zxw"); x.http().request(HttpMethod.PUT, params, new Callback.CommonCallback() { @Override public void onSuccess(String result) { } @Override public void onError(Throwable ex, boolean isOnCallback) { } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } });
4.文件上传。
上传文件使用POST请求。
下面给出一个请求事例,代码如下,
String path="/mnt/sdcard/test.jpg";//文件路径 RequestParams params = new RequestParams(url); params.setMultipart(true);//开启multipart表单 params.addBodyParameter("file",new File(path)); x.http().post(params, new Callback.CommonCallback() { @Override public void onSuccess(String result) { } @Override public void onError(Throwable ex, boolean isOnCallback) { } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } });
上传文件,是以multipart表单的形式,这和在网页上上传文件的原理是一样的!
上传文件是不是很简单呢!
5.文件下载。
首先看看一个回调接口,Callback.ProgressCallback,该接口提供了7个回调方法,
new Callback.ProgressCallback<String>() { @Override public void onWaiting() { } //请求开始的时候回调 @Override public void onStarted() { } //下载的时候不断回调的方法 @Override public void onLoading(long total, long current, boolean isDownloading) { } //成功后回调 @Override public void onSuccess(String result) { } //发生异常时回调 @Override public void onError(Throwable ex, boolean isOnCallback) { } //请求取消时回调 @Override public void onCancelled(CancelledException cex) { } //请求完成时回调 @Override public void onFinished() { } }
该回调方法已经提供了下载进度这样的方法,便于我们显示进度。
照例,给出一个使用事例代码,如下所示,
RequestParams params = new RequestParams(url);//url 文件下载路径 //自定义保存路径,Environment.getExternalStorageDirectory():SD卡的根目录 params.setSaveFilePath(Environment.getExternalStorageDirectory()+"/download/"); //自动为文件命名 params.setAutoRename(true); x.http().post(params, new Callback.ProgressCallback<String>() { @Override public void onWaiting() { } //请求开始的时候回调 @Override public void onStarted() { } //下载的时候不断回调的方法 @Override public void onLoading(long total, long current, boolean isDownloading) { } //成功后回调 @Override public void onSuccess(String result) { } //发生异常时回调 @Override public void onError(Throwable ex, boolean isOnCallback) { } //请求取消时回调 @Override public void onCancelled(CancelledException cex) { } //请求完成时回调 @Override public void onFinished() { } });
定义了下载文件的保存路径,也可以不指定,使用默认的下载路径;并且可以获取文件的名字,为新下载文件命名。
6.缓存的请求。
还是需要介绍一个回调接口,Callback.CacheCallback,该接口有5个回调方法,
new Callback.CacheCallback<String>() { private boolean hasError = false; private String result = null; @Override public boolean onCache(String result) { // 得到缓存数据, 缓存过期后不会进入这个方法. // 如果服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法. // // * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法. // 如果服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的 // 逻辑, 那么xUtils将请求新数据, 来覆盖它. // // * 如果信任该缓存返回 true, 将不再请求网络; // 返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息, // 如果服务端返回304, 则表示数据没有更新, 不继续加载数据. // this.result = result; return false; // true: 信任缓存数据, 不在发起网络请求; false不信任缓存数据. } @Override public void onSuccess(String result) { // 注意: 如果服务返回304 或 onCache 选择了信任缓存, 这时result为null. if (result != null) { this.result = result; } } @Override public void onError(Throwable ex, boolean isOnCallback) { hasError = true; Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show(); if (ex instanceof HttpException) { // 网络错误 HttpException httpEx = (HttpException) ex; int responseCode = httpEx.getCode(); String responseMsg = httpEx.getMessage(); String errorResult = httpEx.getResult(); // ... } else { // 其他错误 // ... } } @Override public void onCancelled(CancelledException cex) { Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show(); } @Override public void onFinished() { if (!hasError && result != null) { // 成功获取数据 Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show(); } } }
主要看看onCache(String result)方法,在setCacheMaxAge设置范围(上面设置的是60秒)内,如果再次调用GET请求,则会调用,
@Override public boolean onCache(String result) { this.result = result; return false; // true: 信任缓存数据, 不在发起网络请求; false不信任缓存数据. }
返回true:缓存内容被返回,相信本地缓存,返回false:缓存内容被返回,不相信本地缓存,仍然会请求网络
带有缓存的请求示例:
BaiduParams params = new BaiduParams(); params.wd = "xUtils"; // 默认缓存存活时间, 单位:毫秒.(如果服务没有返回有效的max-age或Expires) params.setCacheMaxAge(1000 * 60); Callback.Cancelable cancelable // 使用CacheCallback, xUtils将为该请求缓存数据. = x.http().get(params, new Callback.CacheCallback<String>() { private boolean hasError = false; private String result = null; @Override public boolean onCache(String result) { // 得到缓存数据, 缓存过期后不会进入这个方法. // 如果服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法. // // * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法. // 如果服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的 // 逻辑, 那么xUtils将请求新数据, 来覆盖它. // // * 如果信任该缓存返回 true, 将不再请求网络; // 返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息, // 如果服务端返回304, 则表示数据没有更新, 不继续加载数据. // this.result = result; return false; // true: 信任缓存数据, 不在发起网络请求; false不信任缓存数据. } @Override public void onSuccess(String result) { // 注意: 如果服务返回304 或 onCache 选择了信任缓存, 这时result为null. if (result != null) { this.result = result; } } @Override public void onError(Throwable ex, boolean isOnCallback) { hasError = true; Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show(); if (ex instanceof HttpException) { // 网络错误 HttpException httpEx = (HttpException) ex; int responseCode = httpEx.getCode(); String responseMsg = httpEx.getMessage(); String errorResult = httpEx.getResult(); // ... } else { // 其他错误 // ... } } @Override public void onCancelled(CancelledException cex) { Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show(); } @Override public void onFinished() { if (!hasError && result != null) { // 成功获取数据 Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show(); } } });
以上就是xUtils框架提供的网络请求方法。总体感觉,确实很方便!有关xUtils框架的使用就到这里!如果还想了解更多,可以去xUtils的github上看它们的sample。