Android开发之Retrofit/OkHttp使用

2023-10-27

OkHttp
简介

OkHttp是时下最火的Http请求框架,其官网及源码地址如下:

相比于其他网络请求框架,OkHttp有什么优点呢?官方介绍如下:

  • HTTP/2 support allows all requests to the same host to share a socket.
  • Connection pooling reduces request latency (if HTTP/2 isn’t available).
  • Transparent GZIP shrinks download sizes.
  • Response caching avoids the network completely for repeat requests.

从上面的介绍我们可以得出有下面这些优点:

  • 在Http/2的支持下,如果网络请求的host是同一个时,允许这些请求共用一个socket。
  • 使用连接池减少请求延迟。
  • 透明的GZIP压缩,减少数据流量。
  • 支持响应缓存,避免重复的网络请求。
使用
添加依赖
    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
GET请求
        //创建OkHttpClient对象
        OkHttpClient httpClient = new OkHttpClient();
        //创建Request对象
        Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .addHeader("key", "value")
                .get()
                .build();
        
        //get方法同步请求
        try {
            Response response = httpClient.newCall(request).execute();
            if (response.isSuccessful()){
                String result = response.body().string();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
       
        //get方法异步请求,异步请求的回调方法均在子线程中执行
        httpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //请求失败 
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求成功
                String result = response.body().string();
            }
        });
POST请求
        //post请求
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
        String data = "{key:value}";
        RequestBody requestBody = RequestBody.create(mediaType, data);
        Request request1 = new Request.Builder()
                .url("http://www.baidu.com")
                .post(requestBody)
                .build();
        //post同步请求
        try {
            Response response = httpClient.newCall(request1).execute();
            if (response.isSuccessful()) {
                String result = response.body().string();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //post异步请求
        httpClient.newCall(request1).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //请求失败
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求成功
                String result = response.body().string();
            }
        });

拦截器、超时、缓存机制

OKHttp的拦截器分为应用拦截器(Application interceptors)和网络拦截器(Network Interceptors),下图是官方对拦截器的介绍。
在这里插入图片描述
两种拦截器的相对优势官方说明如下:
Each interceptor chain has relative merits.
Application interceptors

  • Don’t need to worry about intermediate responses like redirects and retries.
  • Are always invoked once, even if the HTTP response is served from the cache.
  • Observe the application’s original intent. Unconcerned with OkHttp-injected headers like If-None-Match.
  • Permitted to short-circuit and not call Chain.proceed().
  • Permitted to retry and make multiple calls to Chain.proceed().

Network Interceptors

  • Able to operate on intermediate responses like redirects and retries.
  • Not invoked for cached responses that short-circuit the network.
  • Observe the data just as it will be transmitted over the network.
  • Access to the Connection that carries the request.

翻译过来为:

应用拦截器

  • 不用关系redirects和retries的中间过程
  • 永远只会执行一次,不管response是否从缓存中获取
  • 可以监控原始的请求,不关心其它诸如If-None-Match的Header
  • 允许不调用Chain.proceed()
  • 允许重试多次调用Chain.proceed()

网络拦截器

  • 可以操作redirects和retries的过程
  • 不会调用缓存的response
  • 可以监控网络传输交互的数据
  • 可以获取Connection携带的请求信息

它们的区别在于:Application Interceptor拦截应用层与OkHttp之间的网络响应;而Network Interceptor拦截OkHttp与网络层之间的网络请求响应。应用拦截器通过addInterceptor()的方法添加,而网络拦截器通过addNetworkInterceptor()方法添加。

        //创建拦截器
        Interceptor logInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request2 = chain.request();
                Logger logger = Logger.getGlobal();
                long t1 = System.nanoTime();
                logger.info(String.format("Sending request %s on %s%n%s"
                        , request2.url(), chain.connection(), request2.headers()));
                Response response = chain.proceed(request2);
                long t2 = System.nanoTime();
                logger.info(String.format("Received response for %s in %.1fms%n%s",
                        response.request().url(), (t2 - t1) / 1e6d, response.headers()));
                return response;
            }
        };
	    //为OkHttpClient添加拦截器、超时、缓存控制
        Cache cache = new Cache(new File(Environment.getDataDirectory(), "cache"), 10 * 10 * 1024);
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)//连接超时时间
                .writeTimeout(10, TimeUnit.SECONDS)//写操作超时时间
                .readTimeout(10, TimeUnit.SECONDS)//读操作超时时间
                .cache(cache)//添加缓存
//                .addInterceptor(logInterceptor)//添加应用拦截器
                .addNetworkInterceptor(logInterceptor)//网络拦截器
                .build();

以下是将logInterceptor分别添加成应用拦截器和网络拦截器所得到的打印信息:

//应用拦截器
03-07 08:00:37.760 2550-2606/com.example.study I/global: Sending request http://www.baidu.com/ on null
03-07 08:00:37.850 2550-2606/com.example.study I/global: Received response for http://www.baidu.com/ in 85.0ms
    Server: bfe/1.0.8.18
    Date: Thu, 07 Mar 2019 13:00:36 GMT
    Content-Type: text/html
    Last-Modified: Mon, 23 Jan 2017 13:28:12 GMT
    Transfer-Encoding: chunked
    Connection: Keep-Alive
    Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
    Pragma: no-cache
    Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
//网络拦截器
03-07 08:04:22.471 2812-2849/com.example.study I/global: Sending request http://www.baidu.com/ on Connection{www.baidu.com:80, proxy=DIRECT@ hostAddress=www.baidu.com/183.232.231.172:80 cipherSuite=none protocol=http/1.1}
    Host: www.baidu.com
    Connection: Keep-Alive
    Accept-Encoding: gzip
    User-Agent: okhttp/3.11.0
03-07 08:04:22.511 2812-2849/com.example.study I/global: Received response for http://www.baidu.com/ in 41.8ms
    Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
    Connection: Keep-Alive
    Content-Encoding: gzip
    Content-Type: text/html
    Date: Thu, 07 Mar 2019 13:04:22 GMT
    Last-Modified: Mon, 23 Jan 2017 13:28:12 GMT
    Pragma: no-cache
    Server: bfe/1.0.8.18
    Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
    Transfer-Encoding: chunked

对比两个打印信息发现Sending Request最后的on后面跟的connection应用拦截器为null,而网络拦截器不为null,这说明应用拦截器是先拦截后发送请求的,而网络拦截器则是先发送请求后拦截信息的。

需要注意的是,OkHttp请求返回的response.body().string()方法只能调用一次,若调用两次将会抛出异常。除了使用response.body().string()获取String数据外,还可以通过response.body().bytes()和response.body().byteStream()分别获取字节数组和InputStream输入流。关于OkHttp的更多用法可以到官方的wiki中进一步的了解。

Retrofit

Retrofit是一个基于OkHttp的RESTFUL网络加载框架,它的网络请求工作是通过OkHttp完成的,而Retrofit仅负责网络请求接口的封装。

使用
添加依赖
 implementation 'com.squareup.retrofit2:retrofit:2.1.0'//retrofit 
 implementation 'com.google.code.gson:gson:2.6.2'//Gson 库 
 //下面两个是RxJava 和RxAndroid 
 implementation 'io.reactivex:rxjava:1.1.0' 
 implementation 'io.reactivex:rxandroid:1.1.0'  
 implementation 'com.squareup.retrofit2:converter-gson:2.1.0'//转换器,请求结果转换成Model 
 implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'//配合Rxjava 使用
创建请求接口
public interface ApiService {

    //使用GET方法请求数据,配合@Query和@QueryMap使用
    @GET("top250")
    Call<DataBean> getTop250(@Query("start") int start, @Query("count") int count);

    //使用POST方法发送form-encoded请求数据,@FormUrlEncoded可以配合@Filed和@FieldMap使用
    @POST("top250")
    @FormUrlEncoded
    Call<DataBean> getTop250ByPost(@Field("start") int start, @Field("count") int count);

    //使用POST方法发送自定义数据类型请求数据
    @POST("top250")
    Call<DataBean> getTop250ByPostBody(@Body DataBean data);
}
使用Retrofit请求数据
        String baseUrl = "https://api.douban.com/v2/movie/";
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiService apiService = retrofit.create(ApiService.class);
        Call<DataBean> top250 = apiService.getTop250(1, 10);
        //同步请求
        try {
            Response<DataBean> execute = top250.execute();
            if (execute.isSuccessful()) {
                DataBean result = execute.body();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //异步请求
        top250.enqueue(new Callback<DataBean>() {
            @Override
            public void onResponse(Call<DataBean> call, Response<DataBean> response) {
                //方法在主线程中回调
                DataBean result = response.body();
            }

            @Override
            public void onFailure(Call<DataBean> call, Throwable t) {
                //方法在主线程中回调
            }
        });

Retrofit的请求方法与请求参数均在请求接口中声明好了,在使用过程中,只需要通过Retrofit的实例获取到请求接口类的代理对象,即可通过代理对象进行网络请求,请求也分为同步和异步两种方式。另外,Retrofit底层默认使用OkHttp进行网络请求,我们可以配置自己的OkHttp各项参数,通过clinet()方法将Retrofit的OkHttpClient设置为我们自己的OkHttpClient。

参考资料:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android开发之Retrofit/OkHttp使用 的相关文章

  • mysql excel 同步数据_EXcel与MySQL之间的数据迁移

    1 将Excel中数据迁移到MySQL中 将Excel转化为CSV格式 记住保存的路径和文件名最好别出现中文 删除属性名 仅保留数据即可 之后用Sublime Text3打开 在file选项中有set file encoding to 选择
  • CompletableFuture使用(一)

    CompletableFuture是java8提供的异步任务创建 回调 编排和异常处理 创建异步任务 1 runAsync Runnable runnable 创建一个没有返回值的异步任务 接受一个Runnable接口的实现类对象 stat
  • 【人脸考勤项目】人脸检测的5种方式

    文章内容 1 人脸检测的5种方法 1 Haar cascade opencv 2 HOG Dlib 3 CNN Dlib 4 SSD 5 MTCNN 一 人脸检测的5种方法实现 1 Haar cascade opencv Haar是专门用来
  • Eclipse导入项目提示No projects are found to import解决办法

    使用Eclipse导入项目时遇到No projects are found to import提示的解决办法 这是因为导入的文件里面缺少两个文件 classpath project 在这里三种方案 1 其他项目中直接复制这两个文件 然后更改
  • R - Sonya and Hotels

    Sonya decided that having her own hotel business is the best way of earning money because she can profit and rest wherev
  • _【linux 学习】1.常见命令 - mij0lb

    目录处理命令 ls ls a 显示隐藏文件 h 人性化阅读 文件大小转为MB GB 原为数据块 l 相当于ll 长列表类型展示文件信息 d 显示目录 ls命令查询得到的文件大小部分 文件 文件大小 目录 目录文件名占用的字节数 并非目录内数
  • 在ubuntu中使用vscode进行C++调试(转载)

    0 各种代码编辑器及IDE比较 Atom sublime vscode是当前主流的三大跨平台代码编辑器 其他的还有clion kdevelop Qt vim等 1 安装vscode 3种方法 1 从Ubuntu Software安装 推荐
  • WMS:SurfaceView绘制显示

    WMS SurfaceView绘制显示 1 SurfaceView控件使用 1 1 Choreographer接受VSync信号 1 2 自定义SurfaceView 1 3 结果 2 SurfaceView获取画布并显示 2 1 Surf
  • ProtoBuf.js 使用技巧

    转 http www maxzhang com 2015 09 ProtoBuf js E4 BD BF E7 94 A8 E6 8A 80 E5 B7 A7 Protocol Buffers Protocol buffers 是一个用来序
  • Java中类名+方法名(){}理解

    public class Test02 public static void main String args Test02 test2 new Test02 test2 increment System out println test2
  • [安全开发]日志敏感信息检测-3-正则合集(手机号、邮箱、车牌号)

    前言 手机号 邮箱 车牌号 前言 从日志中提取所需信息时 建议两端加上 W用于匹配特殊字符 能减少不少误报 W 匹配非单词字符 与 A Za z0 9 等效 手机号 手机号共11位 编码格式如下 前3位 网络识别号 4至7位 地区编码 8至
  • 盲盒游戏开发方案

    盲盒游戏是一种新兴的游戏类型 其核心机制是让玩家在购买时不知道会获得哪一种物品 从而产生一种探索的乐趣 那么 如何开发一个盲盒游戏呢 以下是一些步骤和要点 一 确定游戏目标和规则 在开发盲盒游戏时 首先需要确定游戏的目标和规则 例如 游戏是
  • k8s之挂载NFS到POD中

    写在前面 在k8s之挂载本地磁盘到POD中 一文中我们看了如何将POD中的数据写到本地磁盘中 这种方式要求POD只能在指定的Node上 一旦POD更换Node 数据依然会丢失 所以本文看下如何通过将数据写到NFS中来解决这个问题 下面我们就
  • 07 FPGA阻塞赋值与非阻塞赋值

    阻塞赋值与非阻塞赋值的含义 在组合逻辑电路中使用阻塞赋值 其效果和c语言是一样的顺序执行 但在时序逻辑电路中常使用非阻塞赋值 非阻塞赋值最明显的就是所有语句块以及一个语句块中的不同变量都是在同步时钟控制下并行执行 这样就会出现输入与输出 延
  • Spring MVC组件之HandlerAdapter

    Spring MVC组件之HandlerAdapter HandlerAdapter概述 HandlerAdapter组件是一个处理器Handler的适配器 HandlerAdapter组件的主要作用是适配特定的Handler来处理相应的请
  • 机器学习(周志华) 习题 参考答案 第十三章

    周志华老师的 机器学习 的第13章的习题答案较少 只找到了三篇 分别为链接一和链接二 这两篇文章有几乎所有题目的个人解答 第三个人只对部分题目进行了解答 相关链接将放在题目下方 以下是个人对这章的习题的理解 如有问题 欢迎指正 其中第四题和
  • 在idea中使用maven导入spring-context时找不到依赖(not found)

    解决办法 重新导入maven project即可 写好依赖后 点击idea右边边上的Maven 然后再点击那个下面这个圈圈就可以了重新导入了 如果不行就可能是写错了依赖了 到maven仓库去查看自己需要的依赖及导入写法 https mvnr
  • 【华为OD机试真题 python】直角三角形【2023 Q1

    题目描述 直角三角形 有N条线段 长度分别为a 1 a n 现要求你计算这N条线段最多可以组合成几个直角三角形 每条线段只能使用一次 每个三角形包含三条线段 输入描述 第一行输入一个正整数T 1 lt T lt 100 表示有T组测试数据
  • OPC UA协议报文,基础介绍+Hello报文解析

    消息主要分为 消息头和附加字段 通讯过程 协议标准第一部分进行总体介绍 协议标准第四部分有详细介绍通讯过程 流程介绍 整体流程 连接套接字 Hello 打开安全信道 创建会话 关闭安全信道 关闭套接字 订阅等事件 服务器审核行为 聚合的服务
  • qq文件对方接收后一定会有提示吗_QQ或将推出已读功能,以后假装看不见就要出事啊!大家怎么看?...

    大家都知道在平时我们经常会主动屏蔽或者无视一些消息 尤其是在工作的时候 面对超出自己的工作范畴我们会假装无视 但是近来QQ欲将推出已读功能 QQ的理由是 一旦消息被接受 按照人际交往的规则 是需要反馈的 不反馈是让对方很不舒服的 接着这个消

随机推荐

  • RMS,RMSE,标准差

    几个容易混淆的量 分别为 RMS 均方根值 Mean squared error RMSE 均方根误差 Root mean squared error Standard Deviation 标准差 下面给出三个量的表达公式 均方根值 均方根
  • JS中字符串比较大小判断的问题(转数字比较)

    因为最近你在写JS页面 有时候需要写到验证 就遇到比较的问题 JS验证代码如下 页面效果 前面开始的时间段3 9 21 23会出现验证 10 20不会 问题原因 得到的结果是字符串 不能直接对比大小 字符串对比的话直接比得是第一位的数字 解
  • HDFS操作及命令介绍

    HDFS常用命令
  • 2021年11月世界编程语言排行

    2021年11月世界编程语言排行 11 月头条 PHP 即将失去前 10 名的位置 自 TIOBE 指数启动以来 20 多年前 PHP 一直是排名前 10 的永久玩家 最近 我们看到 PHP 努力保持在前 10 名 PHP 曾经是 Web
  • 腾讯云轻量服务器安装宝塔镜像使用入门教程(初体验)

    腾讯云轻量应用服务器30M峰值带宽24元 月 价格很不错新手站长网选择了一台入门级1核1G的轻量应用服务器lighthouse 镜像安装宝塔Linux面板 新手站长网来详细说下腾讯云香港轻量应用服务器从购买选择到建站入门教程 腾讯云香港轻量
  • JS各种校验规则

    目录 1 校验是否为整数 2 验证开始时间是否大于结束时间 3 校验手机号是否正确 4 校验身份证是否合法 5 校验字符串是否为正整数 6 去除两端空白判断是否为空 7 校验邮箱是否合理 1 校验是否为整数 var flowNum flow
  • 微信支付服务器端代码,APP接入微信支付(后台代码)

    配置参数 private config array appid gt 微信开放平台上的应用id mch id gt 微信申请成功之后邮件中的商户id api key gt 在微信商户平台上自己设定的api密钥 32位 notify url
  • 祖传Python代码,初学者必用,含泪发出

    今天分享几段工作生活中常用的代码 都是最为基础的功能和操作 而且大多还都是出现频率比较高的 很多都是可以拿来直接 使用或者简单修改就可以放到自己的项目当中 日期生成 很多时候我们需要批量生成日期 方法有很多 这里分享两段代码 Python学
  • 华为HJ2 计算某字符出现次数

    a input b input num 0 for i in range len a if b lower a i lower num num 1 print num
  • CUDA基本优化方法

    一 基于编程模型和执行模型的优化方法 1 选取合适的gridDim和blockDim blockDim最好为32的整数倍 因为执行指令的基本单位为线程束 线程束内的所有线程统一执行广播下来的命令 而线程束的线程数量基本为32 当block被
  • xx排排网数据加密(js逆向)

    网址 aHR0cHM6Ly9kYy5zaW11d2FuZy5jb20v 点翻页看抓包信息 这个data就是加密后的数据 这里的key是一段代码 这是解密所需的key 先拿出来格式化看看 这个和加速乐的处理方法是一样的 把evel换成cons
  • 【Pygame经典合集】​​​​​​终极白给大招:让你玩儿到爽(附多款游戏源码)

    导语 嘿 我是木木子 关注我 跟我一起玩游戏啦 其实嘛 最近的话游戏的话实在是没什么可以写的了 很多游戏的话太难仿制起来很费时间 于是 就有了今天这篇小合集 哈哈哈 这是一个pygame的项目 内含4款单个游戏的哦 想玩那款玩儿那款的哈 今
  • RS485通讯接口定义图详解

    RS485采用差分信号负逻辑 2V 6V表示 0 6V 2V表示 1 RS485有两线制和四线制两种接线 四线制只能实现点对点的通信方式 现很少采用 现在多采用的是两线制接线方式 这种接线方式为总线式拓朴结构在同一总线上最多可以挂接32个结
  • docked --debug 功能

    docker不正常时使用查看 太好用了 bip Bridge IP 是Docker的配置选项之一 用于指定Docker守护进程创建的网络桥接接口的IP地址和子网掩码 在设置bip时 确保所指定的IP地址不以0结尾 当使用以0结尾的IP地址作
  • 移动app自动化测试工具发展历程--完整版

    最近在总结关于移动app的自动化测试的系列文章 本来想在7月份推出这个系列 但是又担心7月份的天气太热 开空调费油 所以索性 想到哪就整理到哪 持续的推出来吧 今天先把移动app自动化测试工具总结一下 我大概的搜索了一下 本站的大佬 整理的
  • (C语言)矩阵转置 (10分)

    将一个3 3矩阵转置 即行和列互换 输入格式 在一行中输入9个小于100的整数 其间各以一个空格间隔 输出格式 输出3行3列的二维数组 每个数据输出占4列 输入样例 1 2 3 4 5 6 7 8 9 输出样例 1 4 7 2 5 8 3
  • 自己造一个简易的IOC轮子

    简易的IOC流程编写笔记 首先先对这个小demo做一个说明 首先这个demo是很简易的 里面有一些可以优化的复杂点我设置了TODO 如果你有兴趣的话 可以自己去完善一下 写这个demo就是为了让自己对IOC的一个流程更加熟悉 对于刚开始学习
  • 【ROS工具】ROS基础学习

    ROS基础学习 1 基本介绍 2 实际操作 1 基本介绍 ROS Robot Operating System 是一个机器人操作系统 开始于2007 三个中长期支持版本 对应着Ubuntu的三个LTS版本如下 ROS术语 主节点 ros m
  • 1139 First Contact(unique函数,string.substr()函数)

    PTA 程序设计类实验辅助教学平台 用map套个set来实现邻接表 排序都免了 include
  • Android开发之Retrofit/OkHttp使用

    OkHttp 简介 OkHttp是时下最火的Http请求框架 其官网及源码地址如下 OkHttp官网地址 http square github io okhttp OkHttp源码地址 https github com square okh