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":""}
注意:
- 同步请求不能在Android的主线程中进行,否则会出现崩溃问题
- 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)
}
})
}
注意:
- 文件下载记得要 AndroidManifest 中进行配置权限
- 配置权限后还要在界面中进行动态申请权限
<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有自己实现的日志拦截器。文章来源:https://www.toymoban.com/news/detail-427003.html
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模板网!