Retrofit
是一个适用于Android
和Java
的类型安全的HTTP
客户端,它是对OkHttp的封装。
OkHttp请求网络
单独使用OkHttp的时候,我们是这样用的:
val client = OkHttpClient()
val body = RequestBody.create(MediaType.get("text/plain"),"content")
val request = Request.Builder()
.url("https://www.wanandroid.com/article/list/1/json")
.post(body)
.build()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
//解析结果response.body(),线程切换
}
override fun onFailure(call: okhttp3.Call, e: IOException) {
}
})
- 实例化
OkHttpClient
对象。 - 使用
Request.Builder
实例化Request
对象,同时设置请求地址,参数,方式等。 - 获取
Call
对象, - 使用
Call
对象发起请求,
经过上面四步就可以获取到服务端返回的数据了,但是OkHttp
发起请求的时候新开了线程,而且回调也不在原线程,在Android中我们还需要手动线程切换,切换到UI线程才能展示数据,而且通过response.body()
获取到的结果是String类型,往往我们需要的是一个实体对象,这就需要我们再手动格式化一遍。在第二步创建Request
对象的时候,我们需要设置url,请求方式,header等参数,非常繁琐。
鉴于以上不方便的地方,Retrofit应运而生。
Retrofit请求网络
val retrofit = Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val appService = retrofit.create(AppService::class.java)
runBlocking {
val list = appService.list()
println(Thread.currentThread().name)//main
println(list.data)
}
- 构建 retrofit 实例。
- 构建 APIService 接口实例。
- 执行请求,解析响应。
两种请求方式最大的区别在于请求的构建和结果的处理。
在OkHttp中,我们是用构建者模式创建Request,而在Retrofit中则是使用@GET,@Header这样的注解。
在OkHttp中我们处理响应的数据需要手动序列化,而且显示在UI界面上还需要手动切换线程,在Retrofit序列化数据仅仅需要添加ConverterFactory就可以了,而且得益于对Kotlin挂起函数的支持,线程也是自动切换。
Retrofit注解
请求方法类注解
Retrofit支持下面八种HTTP请求方法注解@GET,@POST,@PUT,@DELETE,@HEAD,@PATCH,@OPTIONS,@HTTP,@HTTP注解支持自定义请求方法,我们可以使用它实现前面七种注解。
@GET("xxxxx")
suspend fun test(): List<String>
以@GET为例,它接受一个字符串作为参数,表示接口的路径,和BaseUrl一起拼接成完整的地址。
@GET("xxxxx/{userId}")
suspend fun test(@Path("userId") userId: Int): List<String>
注解的参数中可以接受占位符,具体值由@Path指定。
标记类注解
Retrofit
提供了@Streaming
,@FormUrlEncoded
,@Multipart
三种标记类注解。
@Streaming
使用该注解之后,响应体的数据用流的形式返回,在现在文件的时候如果不使用该注解,数据就会全部加载到内存,极易造成OOM。@FormUrlEncoded
表示请求体是Form表单,此时Content-Type
的值变为application/x-www-form-urlencoded
。@Multipart
表示请求体是一个支持文件上传的Form表单,此时Content-Type
的值变为multipart/form-data
。
参数类注解
@Headers
@Headers用于配置请求头信息,可以设置多个,该注解作用于方法。
@Headers({"h1: h1", "h2: h2"})
@GET("xxxxx")
suspend fun test(): List<String>
@Header
@Header可以用于动态设置请求头信息,作用于参数
@GET("xxxxx")
suspend fun test(@Header("h3") h:String): List<String>
@Query
@Query和@QueryMap用于设置查询参数,一般和@GET一起使用。不同的是@QueryMap接受的参数是一个Map。
@GET("xxxxx")
suspend fun test(@Query("name") name:String): List<String>
@Field
@Field和@FieldMap用于发送POST请求的时候设置表单参数,需要和@FormUrlEncoded一起使用。
@FormUrlEncoded
@POST("xxxxx")
suspend fun test(@Field("name") name:String): List<String>
@Part
@Part和@PartMap用于表单字段参数,适用于文件上传,需要配合Multipart使用。
@Multipart
@POST("xxxxx")
suspend fun uploadImage(@Part img:MultipartBody.Part): List<String>
@Body
@Body将实体类或者Map转化为字符串传给服务端。
@POST("xxxxx")
suspend fun test(@Body body:RequestBody): List<String>
//创建RequestBody
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
@Url
@Url用于动态指定请求路径。
@GET
suspend fun test(@Url url:String): List<String>
@Path
@Path 用于填充URL地址的缺省值。
@GET("xxxxx/{userId}")
suspend fun test(@Path("userId") userId: Int): List<String>