• 五月
  • 13
  • 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)

 

原创文章,转载请注明出处

正在加载评论...

0 / 240

警告

确定