OkHttp,蚂蚁金服Android架构面试题

这篇博客介绍了如何在Android中使用OkHttp进行网络请求,包括创建FormBody和MultipartBody,设置连接超时、写入超时和读取超时,以及如何实现自定义拦截器来处理请求和响应头。此外,还强调了Android开发者持续学习和深入理解基础的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

             }


            final String date = response.body().string();
            mHandler.post(new Runnable() {
                @Override
                public 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() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, “请求失败的原因:” + e);
}

        @Override
        public 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() {
                @Override
                public 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() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.e(TAG, "onFailure: " + e);
        }

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

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

| 参数 | 说明 |
| --- | --- |
| text/html | HTML格式 |
| text/plain | 纯文本格式 |
| text/xml | XML格式 |
| image/gif | gif图片格式 |
| image/jpeg | jpg图片格式 |
| image/png | png图片格式 |
| application/xhtml+xml | XHTML格式 |
| application/xml | XML数据格式 |
| application/atom+xml | Atom XML聚合格式 |
| application/json | JSON数据格式 |
| application/pdf | pdf格式 |
| application/msword | Word文档格式 |
| application/octet-stream | 二进制流数据 |

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

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();

@Override
public 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 {
@Override
public 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()是创建一个新的内容呢?其实它是拿到之前的内容,然后把下面的内容添加进去。所以这里其他的内容是不会收到影响的!!!

其实GET请求就是在URL后面追加上相应的参数。

##### 2\. POST请求添加公共请求参数

还是先来一点代码体验一下:

Request requestBuilder = originalRequest.newBuilder()
.addHeader(“key1”, “value1”)
.addHeader(“key2”, “value2”)
.addHeader(“key3”, “value3”)
.addHeader(“key4”, “value4”)
.addHeader(“key5”, “value5”)
.build();


和上面的类似,只是写法不同而已!因为POST请求添加的是相应的header。

整体的代码如下:

public class PublicInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {

    Request request = chain.request();

    if ("GET".equals(request.method())) {
        //GET请求的处理
        HttpUrl build = request.url().newBuilder()
                .addQueryParameter("key1", "value1")
                .addQueryParameter("key2", "value2")
                .addQueryParameter("key3", "value3")
                .addQueryParameter("key4", "value4")
                .addQueryParameter("key5", "value5")
                .build();

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

最后

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

以下是今天给大家分享的一些独家干货:

友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

以下是今天给大家分享的一些独家干货:

[外链图片转存中…(img-4WUYyc5W-1630937939597)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值