使用Retrofit2进行json请求是个老生常谈的问题,值得单独水一期
总体来说,Retrofit2传递json有三种方法
首先初始化一下,这里使用官方提供的GsonConverter
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
val retrofit = Retrofit.Builder().client(OkHttpClient.Builder().build())
.baseUrl(baseUri)
.addConverterFactory(GsonConverterFactory.create())
.build()
一、直接传递body
这种方法是最常见,写法最复杂的方法
首先,create里添加一个接收body参数的方法
@POST(data)
suspend fun data1(@Body body: RequestBody):Bean
然后写一个string转body的方法
fun jsonToBody(json:String) = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json)
接下来就可以愉快地写代码了
val json = "这是要传递的json"
val data = Retrofit.data1(jsonToBody(json))
二、传递对象
这种方法需要在Converter里把对象转换成body,当然官方提供的Converter(包括我们现在使用的GsonConverter)已经帮我们做好这一步,所以我们直接使用就行
@POST(data)
suspend fun data3(@Body any:Any):Bean
class Data(val name:String)
val map = mutableMapOf<String,Any>()
map["参数1"] = 1
map["参数2"] = '2'
map["参数3"] = "3"
map["参数4"] = Data("小明")
val data = Retrofit.data3(map)
或
class PostData(val data1:String,val data2:Int)
val data = Retrofit.data3(PostData("参数1",2))
这里Any可以传任何一个非String类型的值,只要你能确保传入的参数能序列化成你需要的json就行,传入的对象会在Converter里被转换成Body
三,传递String
很多时候,我们希望直接传递String json,而不是在传递前还得考虑序列化的问题
我们希望有这样一个方法:
@POST(data)
suspend fun data2(@Body json:String):Bean
然而上面已经说了,官方提供的Converter并不支持String序列化,因此我们需要自己写一个Converter,并且重写requestBodyConverter方法
class StringConverterFactory: Converter.Factory(){
override fun responseBodyConverter(
type: Type,
annotations: Array<Annotation>,
retrofit: Retrofit
): Converter<ResponseBody, *>? {
if(type == String::class.java)
return StringResponseConverter()
return super.responseBodyConverter(type, annotations, retrofit)
}
override fun requestBodyConverter(
type: Type,
parameterAnnotations: Array<Annotation>,
methodAnnotations: Array<Annotation>,
retrofit: Retrofit
): Converter<*, RequestBody>? {
if(type == String::class.java){
return StringRequestConverter()
}else
return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit)
}
class StringResponseConverter: Converter<ResponseBody, String> {
override fun convert(value: ResponseBody): String? {
return value.string()
}
}
class StringRequestConverter: Converter<String, RequestBody>{
override fun convert(value: String): RequestBody =
RequestBody.create(MediaType.parse("application/json; charset=utf-8"),value)
}
}
val retrofit = Retrofit.Builder().client(OkHttpClient.Builder().build())
.baseUrl(baseUri)
.addConverterFactory(StringConverterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build()
这样,Retrofit2就具备了把String转换成body的能力了,然后就可以这样写
@POST(data)
suspend fun data2(@Body json:String):Bean
val json = "这是要传递的json"
val data = retrofit.data2(json)