get请求:
//直接添加参数
@GET(dataUrl)
fun getData1(@Query("data") data:String):BaseBean<Any>
//map添加参数
//@JvmSuppressWildcards
@GET(dataUrl)
fun getData2(@QueryMap map:Map<String,Any>):BaseBean<Any>
//在链接里添加参数
@GET("$dataUrl/{id}")
fun getData3(@Path("id") id:Int)
post请求:
//直接添加参数
@FormUrlEncoded
@POST(dataUrl)
fun postData(@Field("data") data: String):BaseBean<Any>
//map添加参数
@JvmSuppressWildcards
@FormUrlEncoded
@POST(dataUrl)
fun postData2(@FieldMap map: Map<String, Any>):BaseBean<Any>
postJson请求
//直接传对象,@Body会把any转成json
@POST(dataUrl)
fun postJson(@Body any:Any):BaseBean<Any>
//同上,@Body会把map转成json,其实这方法有点多余,因为map也是any的子类
@POST(dataUrl)
fun postJson(@Body map:Map<String,Any>):BaseBean<Any>
//如果要传的已经是个String类型的json,或者其他基础数据类型,则需要转成RequestBody再传递
@POST(dataUrl)
fun postJson(@Body jsonBody: RequestBody):BaseBean<Any>
//json转RequestBody的方法
fun jsonToRequestBody(json:String): RequestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json)
当然也可以自己实现Converter来实现直接传String json的方法
首先实现Converter:
object StringConverterFactory: Converter.Factory(){
override fun responseBodyConverter(
type: Type,
annotations: Array<Annotation>,
retrofit: Retrofit
): Converter<ResponseBody, *>? {
if(type == String::class.java)
return object :Converter<ResponseBody, String> {
override fun convert(value: ResponseBody): String? {
return value.string()
}
}
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 object :Converter<String,RequestBody>{
override fun convert(value: String): RequestBody? {
return RequestBody.create(MediaType.parse("application/json; charset=utf-8"),value)
}
}
return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit)
}
}
添加Converter:
Retrofit.Builder().client(builder.build())
.baseUrl(baseUrl)
.addConverterFactory(StringConverterFactory)
.addConverterFactory(GsonErrorConverterFactory())
……
然后就可以直接传json了
@POST(dataUrl)
fun postJson(@Body json: String):BaseBean<Any>
文件上传
//上传文件使用MultipartBody.Part,上传多个文件使用List<MultipartBody.Part>
//上传单个文件
@Multipart
@POST(dataUrl)
fun upLoadFile(@Part part:MultipartBody.Part):BaseBean<Any>
//上传多个文件
@Multipart
@POST(dataUrl)
fun upLoadFiles(@Part parts:List<MultipartBody.Part>):BaseBean<Any>
/**
* 生成上传文件的MultipartBody.Part参数
* name:上传文件的参数名
* file:要上传的文件
*/
fun getFilePart(name:String, file:File): MultipartBody.Part{
val type = getMimeType(file) ?:"multipart/form-data"
return MultipartBody.Part.createFormData(name,file.name, RequestBody.create(MediaType.parse(type),file))
}
//生成多文件上传的List<MultipartBody.Part>,多文件上传分为两种,一种是多个文件参数对应多个文件,另一种是单个参数对应多个文件
/**
* 多参数多文件上传参数
*/
fun getParts(fileMay:Map<String,File>):List<MultipartBody.Part>{
val list = arrayListOf<MultipartBody.Part>()
fileMay.forEach{list.add(getFilePart(it.key,it.value)) }
return list
}
/**
* 同一参数名多图片上传
*/
fun getParts(name:String,files:List<File>):List<MultipartBody.Part>{
val list = arrayListOf<MultipartBody.Part>()
files.forEach { list.add(getFilePart(name,it)) }
return list
}
带文本的文件上传
//带文本的文件上传可以使用MultiaprtBody
//文本+文件上传
@POST(dataUrl)
fun textAndFile(@Body body:MultipartBody):BaseBean<Any>
//根据上传的数据不同,组合成不同的MultipartBody
//文本+文件上传
fun getMultipartBody(params:Map<String,Any>,parts:List<MultipartBody.Part>):MultipartBody{
val builder = MultipartBody.Builder()
builder.setType(MultipartBody.FORM)
params.forEach{
builder.addFormDataPart(it.key,it.value.toString())
}
parts.forEach {
builder.addPart(it)
}
return builder.build()
}
返回文件的mimetype
fun getMimeType(file: File):String? = URLConnection.getFileNameMap().getContentTypeFor(file.name)
//uri文件上传
android10之后,上传文件不可避免地需要调用uri,retrofit也支持直接上传uri,就像上传file一样,只需要重写RequestBody三个方法即可
定义一个UriRequestBody继承RequestBody,并且重写contentType(),writeTo(),contentLength()三个方法
class UriRequestBody(val context: Context, val uri: Uri):RequestBody(){
override fun contentType(): MediaType = MediaType.get(context.contentResolver.getType(uri)?:"multipart/form-data")
override fun writeTo(sink: BufferedSink) {
val ips = context.contentResolver.openInputStream(uri)
ips?.let { sink.writeAll(Buffer().readFrom(it,contentLength())) }
}
override fun contentLength() = context.contentResolver.openFileDescriptor(uri,"r")?.statSize?:-1L
}
使用:生成上传文件的MultipartBody.Part参数
fun getpart(context: Context,name:String,fileName:String,uri:Uri): MultipartBody.Part{
return MultipartBody.Part.createFormData(name,"",UriRequestBody(context,uri))
}