- 五月
- 14
- load
- load
【Retrofit第二篇】Converter,具有灵魂的请求 2021-05-14 20:48:43
在介绍@Body的时候,我介绍了addConverterFactory这东西,这是什么?
这个是请求转换器,如果你掌握了这东西,retrofit对你来说就开始逐渐好用了。
我们提交body时,没有加上ScalarsConverterFactory.create()就出错了,那么,ScalarsConverterFactory是什么东西?
你可以理解它是通用转换器,直接ctrl进去不难发现,就是把基础数据类型和字符串转成字符串
然后又转成bytes数组,存放到body里
这意味着,这个转换器不能转换我们自己定义的对象(就是想转它也不知道要转成什么)
“我大概知道有这么一个东西了,如果我要把对象转换成json,难道要自己写转换器?”
一般通用转换器在github都能找到,不过官方就提供了一个方案,用gson。
还记得一开始我们引入的依赖吗?其中就有gson,使用方法也很简单
addConverterFactory(GsonConverterFactory.create())
这个时候,你的数据类就能解析成json并用于请求了
最终请求:
假设服务器视为请求成功,并只返回了1
那么会请求成功,日志会输出1
如果你把Call的泛型改成Int会怎样?
没问题,response的body会因为你的泛型而改变,而GsonConverterFactory实际是在gson工作,而gson会解析基本数据类型。
即使你的Call泛型放着一个数据类,只要服务器返回的json和你的数据类对得上,就能解析。
假设你家服务端,返回的东西都是密文,解密后才是json,该怎么办?
这个时候,就得自定义转换器了。
创建一个类,这里就叫DecompressConverterFactory好了,继承Converter.Factory,得到如下基本结构
根据这两个方法得知,我们还需要写两个继承Converter的类,用于处理过程。
假设,你家服务端数据明文是 {"name":"张三","age":24}
而密文数据是(用base64编码模拟一下加密):eyJuYW1lIjoi5byg5LiJIiwiYWdlIjoyNH0=
接收数据也需要加密,那么就这么做
然后就是调用:
最终请求:
服务端返回:
日志输出:
提交的明文: {"age":1,"name":"name"}
提交的密文: eyJhZ2UiOjEsIm5hbWUiOiJuYW1lIn0=
解析服务端内容: {"name":"张三","age":24}
search: Test(name=张三, age=24)
在转换器的帮助下,我们就不用关心格式化的问题了。
至于转换器还有什么写法,建议阅读下别人是如何写的,例如GsonConverterFactory,内容不多,有助于自己理解。
直接阅读Converter.Factory源码时可以发现,它还有一个抽象方法,叫stringConverter,这是什么?
根据注释说明可以了解,它是转换@Field,@FieldMap,@Header,@HeaderMap,@Path,@Query,@QueryMap这些非@body请求参数注解的。
也就是说,你仅用@Body的情况下,stringConverter是不会回调的。
以@Field为例,我们意图是传递一个对象,它自动给我们转换成base64,并发送给服务器,那么就这么写。
data class:
请求方式:
转换器:
最终请求
可见,即使我们传了对象,也自动给我们转码了。
注意:
1.base64可能会有等号,这个转换若出现了等号,会自动转码为%3D
2.只要你写了转换器,responseBodyConverter必须要实现,否则会报错
原创文章,转载请注明出处