前言
Retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了Okhttp。
准确来说,Retrofit是一个RESTful的http网络请求框架的封装。
因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。
https://square.github.io/retrofit/
代理HTTPS无法请求
Android要配置networkSecurityConfig
查看
https://www.psvmc.cn/article/2019-04-03-win-proxy.html
基本配置
添加网络权限
1 | <uses-permission android:name="android.permission.INTERNET"/> |
添加依赖
1 | implementation ("com.squareup.retrofit2:retrofit:2.9.0") |
Kotlin整体示例
新版本的Retrofit已经可以方便使用Kotlin的协程。
添加实体
1 | import java.util.List; |
用户
1 | data class UserItem(val name: String, val sex: String) |
服务接口
添加suspend关键字,返回类型Response<T>
ServiceUser.kt
1 | package com.xhkjedu.zxs_android.api |
suspend
关键字的核心作用是允许函数暂停协程的执行(而非阻塞线程),并在适当的时候恢复,它是 Kotlin 协程实现 “高效异步编程” 的基础。
Retrofit 支持用 suspend
标记接口方法,直接在协程中调用,无需回调;
管理类
ApiManager.kt
1 | import android.annotation.SuppressLint |
简单调用
1 | GlobalScope.launch { |
ViewModel中调用
BaseViewModel
如果使用Jetpack Compose
BaseViewModel.kt
1 | import androidx.compose.runtime.mutableStateOf |
调用
UserViewModel
1 | import android.util.Log |
常见配置
请求头设置
HeaderInterceptor.kt
1 | import android.util.Log |
其中
intercept 会在每次请求的时候都触发。
超时时间设置
1 | val client = OkHttpClient().newBuilder() |
这三个超时时间分别是:
连接超时时间(Connect Timeout):指的是客户端连接到服务器所需的最大时间。
如果在规定的时间内未能建立连接,则会抛出
java.net.SocketTimeoutException
异常。读取超时时间(Read Timeout):指的是客户端从服务器读取数据的最大时间。比如下载。
如果在规定的时间内未能读取到数据,则会抛出
java.net.SocketTimeoutException
异常。写入超时时间(Write Timeout):指的是客户端向服务器发送数据的最大时间。比如上传。
如果在规定的时间内未能将数据发送完毕,则会抛出
java.net.SocketTimeoutException
异常。
建议:
上传下载和普通接口请求的超时时间分开设置。因为两个的时间差别较大。
信任所有证书
1 |
|
请求报错
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
可以按照上面信任证书
结合Flow
BaseViewModel.kt
1 | import androidx.compose.runtime.mutableStateOf |
UserViewModel.kt
1 | import android.util.Log |
服务参数
Query参数
1 |
|
Path参数
1 |
|
Body参数
数据类
首先定义数据类:
1 | data class UserRequest( |
然后在 Retrofit 接口中使用 @Body
注解:
1 | import retrofit2.Response |
MutableMap
1 | interface ApiService { |
使用时
1 | val params = mapOf( |
报错
Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?>
原因是:
因为参数Map的value类型Any,在Java中这个value的类型是Object,可以被Retrofit识别,但对于kotlin来说,retrofit会把Any识别成 ?,所以就报出了错误。
解决方法
Any前要添加@JvmSuppressWildcards
。
请求体是空
如果请求体要求是{}
不传参数的话,请求体是空,不是{}
,写成Map<String, Any?>
这样也不行,会提示不知道值的类型。
我们可以写成这样
1 |
|
调用
1 | ApiManager.menuService.apiSysFacilityResourceQuerylist(mapOf()) |
匿名对象
1 | interface ApiService { |
使用时
1 | apiService.updateInfo( |
Form 表单参数
@Field
强制依赖 @FormUrlEncoded
,会自动设置请求头为表单类型。
单个参数
1 |
|
表单Map
1 | interface ApiService { |
使用时
1 | val params = mapOf( |
MutiPart
1 | interface ApiService { |