对于Android
来说网络请求的实现有很多,例如可以直接使用没有封装的HttpUrlConnection
,或者使用一些已经进行了封装的例如Volley
、OkHttp
,这些封装好的开源库也是不错的,如果要讲的话也可以单独写好几篇文章,如果需要了解Volley
原理的的可以查看这两篇文章Android Volley源码分析(一)、Android Volley源码分析(二)。但是今天要说的是现在Android
开发人员进阶必备的网络库Retrofit
,也是现在最流行的,如果你之前使用过OkHttp
那么恭喜你有了一个好的优势,因为Retrofit
内部就是使用OkHttp
进行请求的。Retrofit
做的只是封装请求参数、Header
、Url
等信息,最后再传给OkHttp
完成请求,请求完之后OkHttp
在传回给Retrofit
。下面来说下Retrofit
的基本使用。
本章介绍的都是入门的知识,只做一个引导作用,大神请自动跳过
Retrofit
对于Retrofit
的介绍我引用官方的一句话Type-safe HTTP client for Android and Java by Square, Inc.
简单的翻译一下就是:对于Android
与Java
是一个类型安全的Http
请求库。它是使用注释来描述Http
请求,主要有以下特点:
- 支持
URL
参数替代与query
参数的查询 - 对于请求
body
类型的转换(例如:Json
、protocol buffers
) - 支持
Multipart
请求与文件上传
配置
现在已经更新到Retrofit2
了,对于Android
来说直接在Gradle
中配置:
|
|
或者查看官网配置最新版本,Retrofit
需要的Android
最低版本为2.3
对于Retrofit2
就不需要配置OkHttp
依赖了,因为它默认会一起配置,在使用Retrofit
时,会使用一些类型的转换,提供了以下6
中流行的类型供选择
- Gson: com.squareup.retrofit2:converter-gson
- Jackson: com.squareup.retrofit2:converter-jackson
- Moshi: com.squareup.retrofit2:converter-moshi
- Protobuf: com.squareup.retrofit2:converter-protobuf
- Wire: com.squareup.retrofit2:converter-wire
- Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
在
Gradle
中配置与Retrofit
对于的版本号1compile 'com.squareup.retrofit2:converter-gson:2.1.0'
使用
前面说了Retrofit
是使用注释来定义请求,且它定义的注释是在接口方法中,所以每一个方法都必须要有相应的Http
注释与请求的URL
。Retrofit
支持5
中内置的注释的Http
请求方式:GET
、POST
、PUT
、DELETE
与HEAD
。下面来看下简单的定义。
定义的URL
包括两部分一部分为host
也称为baseUrl
例如:https://api.github.com
,别一部分为path
例如:users/list
,我们在注释中定义的url
一般为path
部分。
以下的介绍都是针对
Retrofit2
来进行的,与Retrofit1.9
有的地方还是有区别。
GET
|
|
也可以直接带参数
|
|
Path
其实也可以使用动态更新的方式来定义path
,再path
中通过使用{}
来定义需要动态替代的字段,再到方法中使用@Path()
来定义替代的变量值
|
|
@Path
还有一个可选的字段encoded
默认为false
,如果为true
将会对特殊的字符进行编码转换,例如key
为address
的value
为maer-se
,默认编码的url
为group/maer-se/users
,但如果对encoded
设置为true
将会对-
字符进行转换最终变成了group/maer%2Dse/users
,使用如下:
|
|
后续的
Query
、QueryMap
、Part
、PartMap
、Field
与FieldMap
都有这个特性
Query
参数查询也可以通过使用@Query()
来定义
|
|
QueryMap
如果参数过多可以借助@QueryMap
来构造Map
|
|
同时如果在调用.groupList
时,只要参数的类型不为基本类型(int
、double
等),或者将基本型转换为Integer,Double
等时可以为null
,如果为null
那么Retrofit
将会忽略不会匹配该参数。另外在使用QueryMap
时,可以动态匹配你需要的参数,没有提供的参数将会自动忽略,例如:
|
|
这个请求的url
为https://api.github.com/group/2/users?user=Marcus
对于address
将自动忽略。
说了这么多还是以一个示例来展示整个调用流程,下面的示例是
Github
上的
示例
定义接口
|
|
Contributors
是一个实体类,对应于请求之后返回的数据类型
|
|
通过Retrofit
生成你定义的接口,其中响应的数据是Json
类型,所以要对body
做相应的转化,通过添加Converter
,如果没有添加Converter
它默认是使用OkHttp
的ResponseBody
与ResponseBody
对于后续POST
设置的@Body
|
|
使用
GsonConverterFactory.create()
必须在Gradle
中配置了前面所说的6
种类型中的Gson
每一个Call
都是来自于创建的接口通过同步或者异步请求远程服务而获得。在调用接口的方法时可以传入对应的参数数据
|
|
最后同调用Call
的execute
执行同步请求,或者调用Call
的enqueue
来执行异步请求,获取响应的结果
|
|
POST
对于一个对象可能会作为Http
请求的body
。这时可以使用@Body
注释
|
|
这个对象也可以使用Retrofit
的converter
来进行特殊的转化,如果没有添加converter
它将默认使用RequestBody
FormUrlEncoded And Multipart
对于接口定义的方法也可以发送form-encoded
与multipart
数据类型。
Field And FiledMap
对于form-encoded
的数据类型,一般Content-type
为x-www-form-urlencoded
可以使用@FormUrlEncoded
来对方法进行注释说明,每一对的key-value
可以使用@Field
来进行定义,分别提供key
与value
。对于多对数据可以使用@FieldMap
进行统一设置,使用与@QueryMap
类似。
|
|
如果有多个相同的字段,可以通过数组来定义字段的值
|
|
FromUrlEncoded
与Query Parameter
的主要区别是,前者是POST
后者是GET
,同时前者的请求数据是放在request body
中,而后者是放在url
中。
Part And PartMap
需要Multipart
请求时即上传文件时,一般Content-type
为multipart/form-data
,只要在方法上面使用@Multipart
注释,同时对于Parts
部分的定义可以使用@Part
注释,相应的@PartMap
也存在
|
|
Multipart
默认也是使用RequestBody
操作它的序列化,或者也可以使用converter
来实现。
Headers And Header
@Headers
注释是为方法添加静态的headers
,且相同的name
不会被覆盖,都会包含到请求中;而@Header
注释是为方法添加动态的header
,它将会相当与参数来对@Header
进行提供,如果这个参数的值为null
,那么它将会被忽略。
|
|
如果是最新版本的
Retrofit2.1
,也支持@HeaderMap
示例
再来贴一个多说文章请求的完整示例,先来看下需要请求示例资源
相信应该很清楚了,请求方式为GET
,请求的Url
为http://idisfkj.duoshuo.com/api/threads/list.json?short_name=idisfkj&order=desc&limit=30&nonce=57f1b19209428
,请求查询的参数为short_name
、order
、limit
与nonce
,Ok
需要知道的都有了,下面来code
。
|
|
|
|
|
|
如果你看到这里,那么恭喜你对
Retrofit
也入门了,后续我还会继续探究与大家进行分享。