- 五月
- 13
- load
- load
【Retrofit第一篇】你的Retrofit使用方式可能是错的 2021-05-13 21:49:40
我偶尔会收到一些项目,无一例外,网络请求框架是retrofit2,我16年开始认识它的,它发布的时间比16更早,至今还是网络请求框架的最优解决方案。可见retrofit2还是值得学习的。
Retrofit,直译过来就是封装,它并不是一个网络请求库,而是okhttp3的封装,可以理解是okhttp3的加强版。
虽说我收到的项目网络请求大多数是retrofit2,但请求方式很多时候是畸形的。硬是把retorfit封装成volley
语法类似这样:
直接用volley不就好了?当然volley语法不是这样,只是搞成这样很显然违背了retrofit这个名字。
虽说retrofit确实有点复杂,也确实需要我们二次封装,但它自身就封装得很好,其实我们只需要进行少量封装就能很好地使用这个框架。
添加依赖(可能需要通过科学手段访问):https://square.github.io/retrofit/
注意,官方提到了Retrofit requires at minimum Java 8+ or Android API 21+.
也就是说,不支持安卓4.4或以下。如果一定要支持安卓4.4或以下,你只能用2.6.0,不能比这个更高了。
还好,这个版本支持协程。
本篇文章以当前最新版本(2.9.0)进行编写
依赖引入:
严格来说,你仅仅引入第一个就能实现网络请求的基本操作,就是有点痛苦。
一般要引入多个东西,如果还要捕获日志,或者使用协程,rxjava这些,还要引入更多,一般为了用个retrofit就得引3-4个依赖。
你的清单文件记得加上网络请求权限
如果你的请求要支持http,因此还要在application加上这一段
然后看看最简单的网络请求感受一下,例如请求个百度搜索?
如果你是第一次接触,相信你跟当初的我想法差不多,好好的get请求非要拆成几块也算了,为了请求个接口我还得声明个interface,不是更麻烦吗?
看起来确实是这样,不过刚刚也提到了,这是最简单的操作,而且项目中总不可能只有一两个接口吧?那retrofit确实不合适。
那么,虽说不是一个很好的感受,现在开始说明retrofit要怎么用。
首先,我们要学习这个interface要怎么用,不过说interface前,要先说下注解相关
请求方法:
- @GET get请求
- @POST post请求
- @PUT put请求
- @DELETE delete请求
- @PATCH patch请求,该请求是对put请求的补充,用于更新局部资源
- @HEAD head请求
- @OPTIONS options请求
- @HTTP 自定义请求方法,它拥有三个属性:method(方法名)、path(请求路径)、hasBody(是否有body)
请求头:
- @Headers 用于添加固定请求头,可以同时添加多个,通过该注解的请求头不会相互覆盖,而是共同存在
- @Header 作为方法的参数传入,用于添加不固定的header,它会更新已有请求头
响应标记:
- @FormUrlEncoded 表示请求发送编码表单数据,每个键值对需要使用@Filed注解
- @Multipart 表示请求发送form_encoded数据(使用于有文件上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值
- @Streaming 表示响应用字节流的形式返回,,如果没有使用注解,默认会把数据全部载入到内存中,该注解在下载大文件时特别有用
请求参数:
- @Body 作用于请求消息的body里,例如传统的post请求,参数就是放在body里,这个也一样,但这个你可以自定义任何内容。
- @Filed 多用于Post方式传递参数,需要结合@FromUrlEncoded使用,即以表单的形式传递参数
- @FiledMap 多用于Post请求中的表单字段,需要结合@FromUrlEncoded使用
- @Part 用于表单字段,Part和PartMap与@multipart注解结合使用,适合文件上传的情况
- @PartMap 用于表单字段,默认接受类型是Map
,可用于实现多文件上传 - @Path 用于Url中的占位符
- @Query 用于Get请求中的参数
- @QueryMap 与Query类似,用于不确定表单参数
- @QueryName 自定义Get请求参数格式,当你不希望格式为url?$key=$value时,这个就用得上了。
- @Tag 为你这次请求起个名字,可以通过response.tag()把名字获取回来,有点像view.tag
- @Url 指定请求路径
请求:
这是最基本的请求,不带任何参数的请求
那么请求时,将会以下方式请求
如果我的url,其中一个路径是动态的,那么可以这么写
请求方法:
最终请求:
既然url可以部分动态,那我能不能这样写?
最终请求
可以是可以,只不过帮你转义了。
get请求少不了参数,是这样操作吗?
很遗憾,当你执行的时候会报错:
java.lang.IllegalArgumentException: URL query string "id={id}" must not have replace block. For dynamic query parameters use @Query.
就是叫我把@Path改成@Query?确实要这样,但你的注解,不能出现任何url参数,也就是说,你得这样操作
传递1234字符串,最终请求:
如果连接是死的,参数是活的,要怎么操作?
请求:
最终请求
当你家服务端接收格式是长这样的:http://www.baidu.com/api/test?id|1&title|string
baiduSearch("id|1","title|string"),最终请求:
如果我的url完全是活的,要怎么操作?
传递123/qwe/zcx?id=123345,最终请求:
这样既不转义也不分割达到完全动态的方式,这东西也许也是新手渴望的东西,甚至想靠这注解封装成自己专属的http请求框架,看呐,经过封装interface都不用创建啦(我就干过这蠢事),现在@Url注解我几乎没用了。
接下来讲下post请求,传参,还是像get那样,加@Query就行?
传递123字符串,最终请求:
怎么回事?不应该传递到body里吗?
请求方法相信大家都明白,GET参数放在url,post参数放在body。但实际上,它们之前最大的区别不过是名字不同,完全可以通过技术手段做到相同的方法,get也可以把参数放在body请求,post也可以把参数放在url上。
因此,我们的注解也会有所不同。
传递1234,最终请求:
我可以不加@FormUrlEncoded吗?不行,一旦用了@Filed就要加,否则会出现以下异常
IllegalArgumentException: @Field parameters can only be used with form encoding. (parameter #1)
如果我post请求参数是动态的,操作和@QueryMap一样,只不过要把@QueryMap改成@FiledMap即可。
如果我的请求是放在body,是某种格式传递的,可能是json,也可能是一串项目定义的字符串,应该怎么做?
注意,用了@Body就不能用@FormUrlEncoded
自定义body需要转换器的支持,因此我们请求过程,需要添加一个转换器,由于我还没开始讲转换器,因此这个转换器可以理解是固定写法。
最终请求:
添加请求头:
请求:
@Headers是静态添加header,没有供你修改的参数,那么介绍第二种。
baiduSearch("1"),最终请求:
如果我想连key都是动态的,那么用这个:
最终请求:
如果你家服务端有个很奇怪的方法,不是GET,不是POST,也不是PUT,而是自定义的方法名,叫GOD
没事,retrofit能拯救这个问题
最终请求:
至于响应标记剩下的部分,等会再细说。
(本来打算一次性吧retrofit2介绍全,结果发现篇幅过长不宜一次性介绍,因此我打算分段介绍retrofit2)
原创文章,转载请注明出处