写点什么

OkHttp、rxJava、Retrofit 联合网络请求(一

用户头像
Android架构
关注
发布于: 1 小时前

1.1.4 创建请求返回的内容

call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.e(TAG, "请求失败的原因:" + e);}


@Overridepublic void onResponse(Call call, final Response response) throws IOException {Headers headers = response.headers();Set<String> names = headers.names();for (String name : names) {Log.e(TAG, "请求的 header" + name);String value = headers.get(name);Log.e(TAG, "值为: " + value + "\n----------------------------------");}


final String date = response.body().string();mHandler.post(new Runnable() {@Overridepublic void run() {mTvShow.setText(date);}});}});


这里要说明的就多了:


  1. 当你的看到 FATAL EXCEPTION: OkHttp Dispatcher 这个异常的时候,恭喜你,你踩到第一个坑了!这个主要是因为response.body().string()只能调用一次,如果你在代码中调用了两次,那么就会出现上面的异常;

  2. 当你异步请求的时候,是不能在子线程修改 UI 的,所以这里我用了一个 Handler 去操作相应的内容

  3. 如果你想看相应的一些内容的话,那么看那个 for 循环那里,你打印一下,就能看到如下的内容,如果不怎么理解的话,找你们后台人员请教一下!一定要虚心哦。


Accept-Ranges →bytesCache-Control →no-cacheConnection →Keep-AliveContent-Length →227Content-Type →text/htmlDate →Wed, 05 Sep 2018 03:41:58 GMTEtag →"5b7b7f40-e3"Last-Modified →Tue, 21 Aug 2018 02:56:00 GMTPragma →no-cacheServer →BWS/1.1Set-Cookie →BD_NOT_HTTPS=1; path=/; Max-Age=300Strict-Transport-Security →max-age=0X-Ua-Compatible →IE=Edge,chrome=1


  1. 如果失败的话,那么就会在 onFailure 中把异常反馈给你!!!


给你贴下整体代码吧!


/1.创建 OkHttpClient 对象/OkHttpClient httpClient = new OkHttpClient();/2.创建请求 Request 内容/Request request = new Request.Builder().method("GET", null).url("https://www.baidu.com/").build();/3.发送请求/Call call = httpClient.newCall(request);/4.创建请求的回调/call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.e(TAG, "请求失败的原因:" + e);}


@Overridepublic void onResponse(Call call, final Response response) throws IOException {Headers headers = response.headers();Set<String> names = headers.names();for (S


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


tring name : names) {Log.e(TAG, "请求的 header" + name);String value = headers.get(name);Log.e(TAG, "值为: " + value + "\n----------------------------------");}


final String date = response.body().string();mHandler.post(new Runnable() {@Overridepublic void run() {mTvShow.setText(date);}});}});


以上步骤就能正常请求相应的数据了,如果还没有数据的话,好好看看代码!

1.2 简单的 POST 请求

关于 POST 请求的话,基本上就是比 GET 请求多一步设置表单的方法,也就是一个 FormBody 对象的设置,以 key、value 的方式设置表单而已,所以这里教你怎么写,然后我贴一下代码就那么滴了,谁让我那么懒呢!!!


表单的写法是这样的:


FormBody formBody = new FormBody.Builder().add("key", "value").build();


其实 add 方法可以被调用多次,添加相应的 key 和 value;


整体的代码是这样的!!!


/1.创建 OkHttpClient 对象/OkHttpClient httpClient = new OkHttpClient();/2.创建相应的表单内容/FormBody formBody = new FormBody.Builder().add("key", "value").build();/3.创建请求 Request 内容/Request request = new Request.Builder().url("https://www.baidu.com/").post(formBody).build();/4.发送请求/Call call = httpClient.newCall(request);/5.创建请求的回调/call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.e(TAG, "请求失败的原因:" + e);}


@Overridepublic void onResponse(Call call, final Response response) throws IOException {Headers headers = response.headers();Set<String> names = headers.names();for (String name : names) {Log.e(TAG, "请求的 header" + name);String value = headers.get(name);Log.e(TAG, "值为: " + value + "\n----------------------------------");}


final String date = response.body().string();mHandler.post(new Runnable() {@Overridepublic void run() {mTvShow.setText(date);}});}});}


POST 和 GET 请求只是请求的方式不同,POST 比较安全,所有内容都依靠表单传递!

2. OkHttp3 进行文件上传

在这里先来个重要的说明:去写 SD 卡的权限一定要加,一定要加!!!


说到文件上传,一般的网络请求都带有文件上传的功能,其实 OkHttp3 也可以上传文件,具体操作步骤如下:


  • 创建 OkHttpClient 对象

  • 创建请求 Request 内容和所有所需参数(这里和其他的请求不同的地方)

  • 获取文件

  • 设置上传文件的类型

  • 获取请求体

  • 创建请求

  • 创建请求的回调


因为其他的内容都差不多,只有关于表单的内容不通,所以这里着重讲一下关于这个表单的问题。


RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("title", "张三").addFormDataPart("image", "zhangsan.jpg", RequestBody.create(MediaType.parse("application/octet-stream"), new File(Environment.getExternalStorageDirectory().getParent() + "/0/123.png"))).build();


一般这种上传文件,基本上都是传递相应的用户图片,修改图片什么的!因为服务器要根据你上传的这张图片进行相应图片的替换。回来说上面那个配置:


  1. 上面第一个"title"那个参数的话,应该是一组 key、value 形式,基本上是根据服务器定的参数为准,可以有多组!

  2. 第二个"image"那个参数的话,基本上就是这个形式的 key、图片名称、图片位置。这样就能锁定一张图片了,这样就构建出一个相应的 RequestBody 对象了。


整体代码是这样的:


/1.创建 OkHttpClient 对象/OkHttpClient httpClient = new OkHttpClient();/2.创建相应的表单内容/RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("title", "张三").addFormDataPart("image", "zhangsan.jpg", RequestBody.create(MediaType.parse("application/octet-stream"), new File(Environment.getExternalStorageDirectory().getParent() + "/0/123.png"))).build();


/3.创建请求 Request 内容/Request request = new Request.Builder().header("key", "value").url("https://www.baidu.com/").post(requestBody).build();


/4.发送请求/Call call = httpClient.newCall(request);/5.创建请求的回调/call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.e(TAG, "onFailure: " + e);}


@Overridepublic void onResponse(Call call, Response response) throws IOException {Log.e(TAG, "onResponse: " + response.body().string());}});


对了忘说了一点,图片是以流的形式进行传递的。所以上面"application/octet-stream"配置的是这种格式,如果是其他的格式呢?给大家一份对照表:参照一下就 OK 了。



基本上你把上面的代码改吧改吧就能上传文件了!!!就酱紫简单。。。

3. OkHttp 的高端配置

3.1 OkHttp 一些基本参数的配置

配置请求时间和连接超时的时间等等


OkHttpClient httpClient = new OkHttpClient.Builder()//设置相应的连接池.connectionPool(new ConnectionPool())//连接超时.connectTimeout(15, TimeUnit.SECONDS)//写入超时.writeTimeout(15, TimeUnit.SECONDS)//读取超时.readTimeout(20, TimeUnit.SECONDS).build();

3.2 OkHttp 拦截器的一些简单理解

往往在项目中,都会有一些关于公共请求参数的一些问题,这里就会用到相应的 OkHttp 拦截器!什么是拦截器呢?简单点说就和埋点差不多。在请求的时候,会走每一个拦截器!想添加什么就添加什么,这里我们通过几个实例讲解一下你就能大概理解了!

3.2.1 日志拦截器

先看下代码,然后我在做一下相应的解释:


public class LogInterceptor implements Interceptor {


private static final String TAG = LogInterceptor.class.getSimpleName();


@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();


/这样就能在请求之前打印相应的内容了/Log.e("url", String.format("Sending request %s on %s %n %s", request.url(), chain.connection(), request.headers()));


/其实下面这个 chain.proceed(request)这个方法,代表请求前和请求后/return chain.proceed(request);}}


这里就是直接打印了一个相应的 LOG,可以获取到一些请求的参数,这里说明一下:


  1. 当你的请求为 GET 请求的时候只能打印一个 Url 地址,也就是request.url()的值了,饮后后面的 headers 获取到的内容为空,因为 GET 请求没有相应的表单信息;

  2. chain.connection()当你使用除了日志拦截器的时候,就会返回空

  3. chain.proceed(request)代表请求响应的结果,所以说明你也是可以修改返回结果的!!!

3.2.2 重定向一个网址链接的拦截器

这个说来就有意思了,当你请求拦截器的时候,正常应该返回百度返回的内容,但是如果你修改了链接的地址会怎么样呢?当然就会返回你修改之后的返回地址了。。。我们看看怎么实现的


public class ResetInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {


Request newRequest = new Request.Builder().method("GET", null).url("https://fanyi.baidu.com/translate?aldtype=16047&query=%E8%BF%9B%E5%BA%A6%0D%0A&keyfrom=baidu&smartresult=dict&lang=auto2zh#zh/en/%E9%87%8D%E7%BD%AE").build();


return chain.proceed(newRequest);}}


对,你没有看错,就这么赤裸裸的换了一个 url 地址,其实Request request = chain.request();这个方法,返回的 Request 就是在创建的时候,创建的 Request,所以,这里你直接,通过拦截器,直接创建一个新的,直接返回就可以了,就没有之前的 Request 什么事情了!!!其实就相当于你把之前的内容重新写了一遍!就酱紫了。。。

3.2.3 添加相应的公共请求参数

其实这个的实现和上面的差不多,也就是替换相应的 Request 的内容!但是这里你要考虑一个问题,就是 GET 请求和 POST 请求的处理方式应该是不同的,多以这里要分情况去处理。否则不能达到你想要的效果的!所以这里我们分开说。先说明一下,GET 请求是在 Url 后面拼接相应的参数,而 POST 请求是在 form 表单中添加相应的参数,所以方式一定是不一样的!!!

1. GET 请求添加公共请求参数

先来一段代码体验一下:


HttpUrl build = originalRequest.url().newBuilder().addQueryParameter("key1", "value1").addQueryParameter("key2", "value2").addQueryParameter("key3", "value3").addQueryParameter("key4", "value4").addQueryParameter("key5", "value5").build();


Request request = originalRequest.newBuilder().url(build).build();


这样就可以添加相应的公共请求参数了,其实开始的时候,我以为 newBuilder()是创建一个新的内容呢?其实它是拿到之前的内容,然后把下面的内容添加进去。所以这里其他的内容是不会收到影响的!!!

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
OkHttp、rxJava、Retrofit联合网络请求(一