OkHttp:使用篇

这篇具有很好参考价值的文章主要介绍了OkHttp:使用篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、 简介

OkHttp 是一个默认高效的 HTTP 客户端:

  • 支持 HTTP/2 允许对同一主机的所有请求共享一个套接字。
  • 连接池减少了请求延迟(如果 HTTP/2 不可用)。
  • 透明 GZIP 缩小了下载大小。
  • 响应缓存完全避免了网络重复请求。

2、引入依赖

implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'

当然网络请求需要网络请求权限,这个不要忘记在 AndroidManifest 中进行配置

<uses-permission android:name="android.permission.INTERNET"/>

3、创建 OkHttpClient 对象

在使用 OkHttp 发送 HTTP 请求时,首先需要获取一个 OkHttpClient 对象,获取 OkHttpClient 对象的方式很简单,在 OkHttp 中大量使用了 Builder 模式。

①、获取默认配置对象

val myHttpClient: OkHttpClient = OkHttpClient.Builder().build()

②、获取自定配置对象

在获取对象时可以指定,连接超时、读写超时、拦截器等配置

val myHttpClient: OkHttpClient = OkHttpClient.Builder()
    //设置连接超时时间
    .connectTimeout(Duration.ofSeconds(30))
    //设置读超时时间
    .readTimeout(Duration.ofSeconds(60))
    //设置写超时时间
    .writeTimeout(Duration.ofSeconds(60))
    //设置完整请求超时时间
    .callTimeout(Duration.ofSeconds(120))
    //添加一个拦截器
    .addInterceptor { chain ->
        val request = chain.request()
        chain.proceed(request)
    }.eventListener(object : EventListener() {
        override fun callEnd(call: Call) {
            super.callEnd(call)
        }
    })
    .build()

4、GET 请求

①、get请求同步(无参数)

fun httpGetSyncTest() {
    val myUrl="https://www.wanandroid.com/banner/json"
    // 创建一个 Request
    val request: Request = Request.Builder()
        .get()//声明用get请求
        .url(myUrl)
        .build()
    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = myHttpClient.newCall(request)

    // 执行同步请求 execute
    val response = newCall.execute()
    // 判断是否请求成功
    if (response.isSuccessful) {
        println("request success")
        println("response ${response.body?.string()}")
    } else {
        println("request fail")
    }
}
 
 //执行结果
request success
response {"data":[{......}],"errorCode":0,"errorMsg":""}

注意:

  1. 同步请求不能在Android的主线程中进行,否则会出现崩溃问题
  2. response.body?.string() 与 response.body?.toString() 的区别

使用toString()只能获取到如下结果:

response okhttp3.internal.http.RealResponseBody@609bc9f

②、get请求异步(无参数)

fun httpGetAsyncTest() {
    val myUrl="https://www.wanandroid.com/banner/json"
    //创建一个 Request
    val request: Request = Request.Builder()
        .get()//声明用get请求
        .url(myUrl)
        .build()
    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = myHttpClient.newCall(request)

    // 执行异步请求 enqueue
    newCall.enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            println("onFailure $e")
        }

        override fun onResponse(call: Call, response: Response) {
            val body = response.body?.string()
            println("request success $body")
        }
    })
}
    
//执行结果
request success {"data":[{......}],"errorCode":0,"errorMsg":""}

③、get请求异步(有参数)

fun httpGetAsyncParam() {
    val urlStr = "https://v.api.aa1.cn/api/api-tianqi-3/index.php"
    //为url添加参数
    val newUrl = urlStr.toHttpUrlOrNull()?.newBuilder()
        ?.apply {
            addQueryParameter("msg", "天津")
            addQueryParameter("type", "1")
        }!!.build()

    //创建一个 Request
    val request: Request = Request.Builder()
        .get()
        .url(newUrl)
        .build()

    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = myHttpClient.newCall(request)

    // 执行异步请求 enqueue
    newCall.enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            println("onFailure $e")
        }

        override fun onResponse(call: Call, response: Response) {
            val body = response.body?.string()
            println("request success $body")
        }
    })

}

5、POST 请求

POST 请求的构建步骤与GET 相似,区别是,在构建 Request 对象时 在post() 方法中,设置需要发送的数据,发送的数据可为目前流行的 JSON 格式数据,也可以模拟 Form表单提交的数据

①、构造 JSON 数据,同步请求

fun httpPostJsonSyncTest() {

    val JSON: MediaType = "application/json".toMediaType()
    val myUrl = "https://www.wanandroid.com/blog/show/2"

    //Json 参数
    val json = JSONObject()
    json.put("username", "Derry-vip")
    json.put("password", "123456")

    //获取 requestBody
    val requestBody: RequestBody = json.toString().toRequestBody(JSON)

    val request: Request = Request.Builder()
        .post(requestBody)
        .url(myUrl)
        .build()

    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = myHttpClient.newCall(request)
    // 执行同步请求execute
    val response = newCall.execute()
    //判断是否请求成功
    if (response.isSuccessful) {
        println("request success")
        println("response ${response.body?.string()}")
    } else {
        println("request fail")
    }
}

②、构造 JSON 数据,异步请求

fun httpPostJsonAsyncTest() {
    val JSON: MediaType = "application/json".toMediaType()
    val myUrl = "https://www.wanandroid.com/blog/show/2"

    //Json 参数
    val json = JSONObject()
    json.put("username", "Derry-vip")
    json.put("password", "123456")

    //获取 requestBody
    val requestBody: RequestBody = json.toString().toRequestBody(JSON)

    val request: Request = Request.Builder()
        .post(requestBody)
        .url(myUrl)
        .build()

    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = OkHttpUtils.myHttpClient.newCall(request)

    //post 异步请求
    newCall.enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            println("onFailure $e")
        }

        override fun onResponse(call: Call, response: Response) {
            val body = response.body?.string()
            println("request success $body")
        }
    })
}

③、构建Form表单

fun httpPostFormSyncTest() {
    val myUrl = "https://www.wanandroid.com/blog/show/2"

    //创建表单
    val formBody: FormBody = FormBody.Builder()
        .addEncoded("username", "Derry-vip")
        .add("password", "123456")
        .build()

    val request: Request = Request.Builder()
        .post(formBody)
        .url(myUrl)
        .build()

    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = OkHttpUtils.myHttpClient.newCall(request)
    // 执行同步请求execute
    val response = newCall.execute()
    //判断是否请求成功
    if (response.isSuccessful) {
        println("request success")
        println("response ${response.body?.string()}")
    } else {
        println("request fail")
    }
}

6、文件下载

fun downFileTest() {
    val downUrl="https://img-blog.yssmx.com/20200614120050920.JPG"
    //创建请求
    val request = Request.Builder()
        .url(downUrl)
        .build()
    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = OkHttpUtils.myHttpClient.newCall(request)

    //异步执行请求
    newCall.enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            //请求失败,提示下载失败信息
            println("onFailure $e")
        }

        override fun onResponse(call: Call, response: Response) {
            //请求成功,获取到资源
            println("success $response")
            //下载文件,将response 转成 inputStream ,然后写入文件中
            writeToSDCard(response)
        }
    })
}

注意:

  1. 文件下载记得要 AndroidManifest 中进行配置权限
  2. 配置权限后还要在界面中进行动态申请权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

7、文件上传

fun upFileTest() {
    val myUrl = "https://mytodoserver.com/new"
    val file = File("path/of/attachment.png")
	
	// 使用 MultipartBody 构造 RequestBody对象
    val requestBody = MultipartBody.Builder()
        .addFormDataPart("image", "attachment.png", file.asRequestBody("image/png".toMediaType()))
        //一定要设置这句
        .setType(MultipartBody.FORM)
        .build()

    val postRequest = Request.Builder()
        .url(myUrl)
        .post(requestBody)
        .build();

    val response = OkHttpUtils.myHttpClient.newCall(postRequest).execute()

    //判断是否请求成功
    if (response.isSuccessful) {
        println("request success")
        println("response ${response.body?.string()}")
    } else {
        println("request fail")
    }
}

8、MediaType介绍

类型 描述
text/html HTML格式
text/plain 纯文本格式,空格转换为 “+” 加号,不对特殊字符编码
text/xml XML格式
text/x-markdown Markdown格式
image/gif gif图片格式
image/jpeg jpg图片格式
image/png png图片格式
application/xhtml+xml XHTML格式
application/xml XML数据格式
application/json 用来告诉服务端,消息主体是序列化后的JSON字符串
application/pdf pdf格式
application/msword Word文档格式
application/octet-stream 二进制流数据
application/x-www-form-urlencoded 参数为键值对形式,在发送前编码所有字符(默认)。如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据
multipart/form-data 不对字符编码,发送大量二进制数据或包含non-ASCII字符的文本,application/x-www-form-urlencoded是效率低下的(需要用更多字符表示一个non-ASCII字符)。需要设定“ <form enctype=‘multipart/form-data’

MediaType对象解析

text/html; charset=utf-8
//解析
type值是text,表示是文本这一大类;
后面的html是子类型,表示是文本这一大类下的html类型;
charset=utf-8 则表示采用UTF-8编码

9、取消请求

在需要的场景上可以通过 Call 对象取消请求 cancel

fun httpGetAsyncCancelTest() {
    val myUrl = "https://www.wanandroid.com/banner/json"
    //创建一个 Request
    val request: Request = Request.Builder()
        .get()//声明用get请求
        .url(myUrl)
        .build()
    // 通过 HttpClient 把 Request 构造为 Call 对象
    val newCall = OkHttpUtils.myHttpClient.newCall(request)

    // 执行异步请求 enqueue
    newCall.enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            println("onFailure $e")
        }

        override fun onResponse(call: Call, response: Response) {
            val body = response.body?.string()
            println("request success $body")
        }
    })

    //在需要的场景上可以通过 Call 对象取消请求
    newCall.cancel()
}

10、拦截器

拦截器可以监控、重写和重试调用。我们可以利用它们在请求发出之前对其进行修改,在响应到达我们的逻辑之前对其进行预处理,或者简单地打印出一些关于请求的细节。

OkHttp有自己实现的日志拦截器。

implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC)
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(loggingInterceptor)
    .build()

也可以自己自定义拦截器文章来源地址https://www.toymoban.com/news/detail-427003.html

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor { chain ->
        val request = chain.request()
        //自定义日志打印
        println("Sending request ${request.url} on ${chain.connection()} ${request.headers}")
        val response = chain.proceed(request)
        //自定义日志打印
        println("Received response for ${response.request.url} ${response.headers}")
        response
    }
    .build()

到了这里,关于OkHttp:使用篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 修改 Zookeeper 的客户端连接端口(默认2181端口)

    Zookeeper 的配置文件通常名为 zoo.cfg,位于 Zookeeper 安装目录的 /conf 目录下。初始配置如下: 修改客户端连接端口的步骤如下: 找到并打开 zoo.cfg 文件 修改客户端端口:找到或添加 clientPort 属性,将其更改为 2281。 保存并重启 Zookeeper 服务。 特别提醒 : 如果在 zoo.cfg 文件中

    2024年04月28日
    浏览(38)
  • 探索高效 Python HTTP 客户端:HTTPX

    项目地址:https://gitcode.com/encode/httpx 在现代 Web 开发中,高效的 HTTP 请求库是不可或缺的一部分。这就是我们要向您介绍的 HTTPX 的地方。HTTPX 是一个高性能、功能丰富的 Python HTTP 客户端,旨在成为 requests 库的一个有竞争力的替代品。 HTTPX 提供了全面的异步和同步支持,包括完

    2024年04月14日
    浏览(51)
  • 【Docker 】Docker 客户端,容器使用,启动容器,启动已停止运行的容器,停止一个容器,进入容器

    作者简介: 辭七七,目前大一,正在学习C/C++,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 docker 客户端非常简单 ,我们可以直接输入 docker 命令来查看到 Docker 客户端的所有命令选项。 可以通过命令 dock

    2024年02月11日
    浏览(44)
  • 【Python】Python 网络编程 ( Socket 套接字简介 | Socket 套接字使用步骤 | Socket 套接字服务端与客户端开发 )

    Socket 套接字 是一种 进程之间的 通信机制 , 通过套接字可以在 不同的进程之间 进行数据交换 ; 在 网络编程 中 , Socket 套接字 主要用于 客户端 与 服务器 之间的 通信 , 大部分 网络相关的应用程序 , 都使用到了 Socket 套接字技术 ; 套接字有两种类型 : 流套接字 : 提供了一个可

    2024年02月15日
    浏览(130)
  • C++基于开源Modbus Tcp 通讯应用客户端(稳定高效,多线程后台状态读取,不卡顿)

    使用多线程后台批量刷寄存器的状态,在某种程度上保证了上层接口读取的时候,不会卡顿, 整体应用效果比较友好。程序应用简单稳定高效,是一个比较不错的尝试。 代码如下: 代码如下: https://download.csdn.net/download/u013083044/87062401

    2024年02月16日
    浏览(48)
  • 网络编程:编写一个TCP客户端与服务端

    用的系统是Ubuntu。 socket用来创建套接字。这个函数服务端与客户端都要使用。 第一个参数用来制定地址族规范,比如 AF_INET(PF_INET) 表示IPv4地址, AF_INET6(PF_INET6) 表示IPv6地址。 第二个参数用来制定套接字的类型规范,如 SOCK_STREAM 表示面向连接的套接字, SOCK_DGRAM 表示面

    2024年02月01日
    浏览(46)
  • Socket实例,实现多个客户端连接同一个服务端代码&TCP网络编程 ServerSocket和Socket实现多客户端聊天

    Java socket(套接字)通常也称作\\\"套接字\\\",用于描述ip地址和端口,是一个通信链的句柄。应用程序通常通过\\\"套接字\\\"向网络发出请求或者应答网络请求。 使用socket实现多个客户端和同一客户端通讯;首先客户端连接服务端发送一条消息,服务端接收到消息后进行处理,完成后再

    2024年02月12日
    浏览(70)
  • 一个支持Sora模型文本生成视频的Web客户端

    大家好,我是 Java陈序员 。 最近 Open AI 又火了一把,其新推出的文本生成视频模型 —— Sora,引起了巨大的关注。 Sora 目前仅仅只是发布预告视频,还未开放出具体的 API. 今天,给大家推荐一个最近十分火热的开源项目,一个支持使用 Sora 模型将文本生成视频的 Web 客户端。

    2024年03月09日
    浏览(55)
  • 【HDFS】每天一个RPC系列----complete(二):客户端侧

    上图给出了最终会调用到complete RPC的客户端侧方法链路(除去Router那条线了)。 org.apache.hadoop.hdfs.DFSOutputStream#completeFile(org.apache.hadoop.hdfs.protocol.ExtendedBlock): 下面这个方法在complete rpc返回true之前,会进行重试,直到超过最大重试次数抛异常。 另外需要注意的是,这个方法在

    2024年02月13日
    浏览(43)
  • 一个基于Kafka客户端封装的工具,Kafka开发效率神器

    GitHub源码https://github.com/zhangchuangiie/SimpleKafka 一个基于Kafka客户端封装的工具,Kafka开发效率神器 封装了常用的Kafka客户端操作,无需维护配置,无需初始化客户端,真正实现了一行代码调用 将连接池的维护封装在工具类里面,多线程使用也无需维护客户端集合 只需要集成1个

    2024年02月05日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包