Android 网络框架:Retrofit2注解篇

2018-11-19  本文已影响0人  怪兽来啦啦啦啦啦

前言

 Retrofit有24个注解,其中12个方法注解,12个参数注解。
 12个方法注解可有细分为以下几种:
  ① 8个HTTP请求注解
  ② 3个标记注解
  ③ 1个请求头注解

HTTP请求注解(共8个)

名称 说明
GET 对应HTTP中的GET请求
POST POST请求
PUT PUT请求
DELETE DELETE请求
PATCH PATCH请求
HEAD HEAD请求
OPTIONS OPTIONS请求
HTTP 用于替代以上方法,自定义HTTP请求

 使用@GET举个例子,代码如下所示:

interface WordService {
 @GET("query")
 fun getWord(@Query("word") word: String, @Query("dtype") dtype: String,@Query("key") key: String): Observable<WordData>
}

 使用@HTTP举个例子,代码如下所示:

interface WordService {
 @HTTP(method = "GET",path = "query",hasBody = false)
 fun getWord(@Query("word") word: String, @Query("dtype") dtype: String,@Query("key") key: String): Observable<WordData>
}

标记注解(共3个)

名称 说明
FormUrlEncoded 请求体是From表单
Multipart 请求体是流
Streaming 直接返回值,不写入内存

FormUrlEncoded
 Field或FieldMap提交数据,不使用FormUrlEncoded会报错,如下所示:

 java.lang.IllegalArgumentException: @Field parameters can only be used with form encoding. (parameter #1)
 java.lang.IllegalArgumentException: @FieldMap parameters can only be used with form encoding. (parameter #1)

 使用了之后会改变编码格式为:“Content-Type: application/x-www-form-urlencoded”
 正确的代码示例如下所示:

 @FormUrlEncoded
 @POST("query")
 fun getWord(@Field("word") word: String, @Field("dtype") dtype: String, @Field("key") key: String): Observable<WordData>

Multipart
 上传文件需要使用到Multipart,使用之后会将编码格式改为:“Content-Type: multipart/form-data”

 @Multipart
 @POST("query")
 fun getWord(@PartMap params: Map<String, String>): Observable<ResponseBody>

 示例代码如下所示:

 var retrofit = Retrofit.Builder()
            .baseUrl("http://v.juhe.cn/xhzd/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(okHttpClient)
            .build()
 var wordService = retrofit.create(WordService::class.java)
 var map = mapOf("word" to "你","json" to "", "key" to "c5c6a09be5cdb204735da11f")
 wordService.getWord(map)
可以看见HTTP请求的报文如下所示: HTTP请求报文

Streaming
 如果下载小文件可以不使用Streaming。下载大文件使用Streaming可以避免Retrofit将文件写入运行内存中避免OOM。

请求头注解(1个)

名称 说明
Headers 添加请求头

 请求头不会相互覆盖,所有具有相同名字的头会包含在请求中。
 示例代码如下所示:

 @Headers("Cache-Control: max-age=640000", "User-Agent: YourAppName")
 @GET("query")
 fun getWord(@Query("word") word: String, @Query("dtype") dtype: String,@Query("key") key: String): Call<WordData>

参数注解(12个)

名称 说明
Body 直接控制Body
Field 添加一个表单数据
FieldMap 添加多个表单数据
Header 添加一个请求头
HeaderMap 添加多个请求头
Query 动态拼接一个参数到URL后
QueryMap 动态拼接多个参数到URL后
QueryName 动态拼接无值参数到URL后
Path 替换相应位置参数
Url 直接传入URL
Part 表示multi-part一个参数
PartMap 表示multi-part多个参数

Body
 当你想直接控制POST/PUT的Body时(替代参数或表单样式发送Body),可以直接使用该注释。

 @POST("query")
 fun getWord(@Body body: RequestBody): Observable<WordData>
 var retrofit = Retrofit.Builder()
            .baseUrl("http://v.juhe.cn/xhzd/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

 var wordService = retrofit.create(WordService::class.java)
 val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), "this is body")
 
 wordService.getWord(body)

Field / FieldMap
 表单上传数据,Field是上传单个数据,FieldMap是上传多个数据。并且需要使用@FormUrlEncoded修饰请求方法,否则报错。
 Field示例代码如下所示:

 @FormUrlEncoded
 @POST("query")
 fun getWord(@Field("word") word: String, @Field("dtype") dtype: String, @Field("key") key: String): Observable<WordData>

 FieldMap示例代码如下所示:

 var map = mapOf("word" to "你","key" to "c5c6a09be5cdb2")
 var retrofit = Retrofit.Builder()
            .baseUrl("http://v.juhe.cn/xhzd/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

 var wordService = retrofit.create(WordService::class.java)
 wordService.getWord(map)
 @FormUrlEncoded
 @POST("query")
 fun getWord(@FieldMap() map: Map<String,String>): Observable<WordData>

Header / HeaderMap
 添加请求体,Header是添加单个请求头,HeaderMap添加多个请求头。请求头不会相互覆盖,所有具有相同名字的头会包含在请求中。
 Header代码如下所示:

 @GET("query")
 fun getWord(@Header("User-Agent") name: String, @Query("word") word: String): Observable<WordData>

 HeaderMap代码如下所示:

 var map = mapOf("Cache-Control" to "max-age=640000","User-Agent" to "YourAppName")
 var retrofit = Retrofit.Builder()
            .baseUrl("http://v.juhe.cn/xhzd/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

 var wordService = retrofit.create(WordService::class.java)
 wordService.getWord(map,"你")
 @GET("query")
 fun getWord(@HeaderMap() name: Map<String,String>, @Query("word") word: String):  Observable<WordData>

Query / QueryMap / QueryName
 动态添加参数到URL
Query
 以下是GET请求示例代码:

 //接口
 @GET("query")
 fun getWord(@Query("word") word: String, @Query("dtype") dtype: String,@Query("key") key: String): Observable<WordData>
 var retrofit = Retrofit.Builder()
            .baseUrl("http://v.juhe.cn/xhzd/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

 var wordService = retrofit.create(WordService::class.java)
 wordService.getWord("word","json","c5c6a09be5cdb2")

 使用了Query之后,URL会拼接成: http://v.juhe.cn/xhzd/query?word=word&dtype=json&key=c5c6a09be5cdb2
QueryMap
 以下是GET请求示例代码:

 @GET("query")
 fun getWord(@QueryMap() map: Map<String,String>): Observable<WordData>
 var wordService = retrofit.create(WordService::class.java)
 var map = mapOf("word" to "你","key" to "c5c6a09be5cdb20473")
 wordService.getWord(map)

 也可以在POST中使用Query或QueryMap,同样是将参数拼接到URL后。
QueryName
 动态添加参数到没有值的Url后面,示例代码如下所示:

 @GET("query")
 fun getWord(@QueryName filter: String): Observable<WordData>

Path
 替换URL中相对应的路径。
 示例代码如下所示:

 @GET("users/{user}/repos")
 fun listRepos(@Path("user") user: String): Call<List<Repo>>
 var retrofit = Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
 val service = retrofit.create(WordService::class.java)
 service.listRepos("octocat")

 传递进来的参数会替换掉"users/{user}/repos"中的user部分,如下所示:

 https://api.github.com/users/octocat/repos

Url
 直接传入Url,代码如下所示:

 @GET()
 fun getWord(@Url url: String): Observable<WordData>

Part / PartMap
 Part表示一个multi-part请求,PartMap表示多个PartMap请求。使用这两个参数需要在接口方法使用Multipart注解。
Part
 存在该注解的参数,有以下三种处理方式:

 @Multipart
 @POST("query")
 fun getWord(@Part("name") filter: String): Observable<WordData>

 @Multipart
 @POST("query")
 fun getWord(@Part() body: MultipartBody.Part): Observable<WordData>

 @Multipart
 @POST("query")
 fun getWord(@Part("name") body: MultipartBody): Observable<WordData>

 MultipartBody.Part上传文件

 var file = File("/sdcard/Pictures/transitions_diagram.png")
 var requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file)
 var multipartBodyPart = MultipartBody.Part.createFormData("SDFile", file.name, requestFile)

 MultipartBody上传文件

 var file = File("/sdcard/Pictures/transitions_diagram.png")
 var requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file)
 var multipartBodyPart = MultipartBody.Part.createFormData("SDFile", file.name, requestFile)
 var multipartBody = MultipartBody.Builder().addPart(multipartBodyPart).build()

PartMap
 如果参数是RequestBody可以直接使用,如果是map,则需要转换成相应的类型使用,示例代码如下所示:

 @Multipart
 @POST("/upload")
 fun upload(@Part("file") file: RequestBody, @PartMap params: Map<String, RequestBody>): Call<ResponseBody>

总结

 结合之前第一篇加上本篇已经涵盖了大多数Retrofit的使用,如果遇到特殊情况需要使用到自定义Converter、CallAdapter、Client。Retrofit的出现我相信作者是为了简化、规范网络请求,因此在使用过程中越简单越好。

上一篇 下一篇

猜你喜欢

热点阅读