RetrofitにおけるConverterによるデータ変換処理
22584 ワード
retrofitにはDate、xxEntityなどのカスタムデータ型が転送されますが、これらのデータ型retrofitはサポートされていません.処理のcoverterを提供する必要があります.@QueryからDateパラメータが入力され、インタフェースは以下の通り: は、カスタムCoverterおよびConverterFactory を提供する. Retrofitに登録されている @POST RequestBodyデータ変換元インタフェース:
改造後:
PkLinkMapエンティティ:
ConverterとConverterFactoryの提供
原理:Retrofitのパラメータ処理はConverterによって処理されており、Converterはインタフェースであり、特殊なデータ型を処理したい場合は、自分で実現して対応するConcerterFactoryを提供すればよい.
Converterインタフェースは次のとおりです.
/**
* banner
* date,retrofite
*/
@GET("banner/json")
fun getBanner(@Query("date" ) date: Date): Call<BaseEntity<Any>>
/**
* Created by mayi on 2020-05-25.
*
*/
class DateConverter :Converter<Date,String> {
override fun convert(value: Date): String? {// Date String, okhttp
return SimpleDateFormat("yyyyMMdd_hhmmss").format(value)
}
}
/**
* Created by mayi on 2020-05-25.
*/
class DateConverterFactory :Converter.Factory() {
override fun stringConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<*, String>? {
// type Date ,
if (type == Date::class.java){
return DateConverter()
}
return super.stringConverter(type, annotations, retrofit)
}
companion object{
fun create(): Converter.Factory {
return DateConverterFactory()
}
}
}
private val retrofit: Retrofit = Retrofit.Builder().baseUrl(BaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(DateConverterFactory.create())// Date Converter Retrofit
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(httpClient)
.build()
/**
*
*/
@FormUrlEncoded
@POST("user/login")
fun toLogin(@Field("username") username:String
,@Field("password") password:String):Call<BaseEntity<Any>>
改造後:
/**
*
*/
@POST("user/login")
fun toLogin4(@Body params: PkLinkMap):Call<BaseEntity<Any>>
PkLinkMapエンティティ:
/**
* Created by mayi on 2020-05-30.
*/
class PkLinkMap :LinkedHashMap<String,String>()
ConverterとConverterFactoryの提供
/**
* Created by mayi on 2020-05-30.
*/
class PkLinkMapConverter : Converter<PkLinkMap, RequestBody> {
private val MEDIA_TYPE: MediaType = "application/json; charset=UTF-8".toMediaType()
override fun convert(value: PkLinkMap): RequestBody? {
value["other_params"] = "this is other params"
return RequestBody.create(MEDIA_TYPE, value.toJson())
}
}
/**
* Created by mayi on 2020-05-30.
*/
class PkLinkMapConverterFactory : Converter.Factory() {
override fun requestBodyConverter(type: Type,
parameterAnnotations: Array<Annotation>,
methodAnnotations: Array<Annotation>,
retrofit: Retrofit): Converter<*, RequestBody>? {
//
if (type== PkLinkMap::class.java){
return PkLinkMapConverter()
}
return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit)
}
companion object{
fun create(): Converter.Factory {
return PkLinkMapConverterFactory()
}
}
}
原理:Retrofitのパラメータ処理はConverterによって処理されており、Converterはインタフェースであり、特殊なデータ型を処理したい場合は、自分で実現して対応するConcerterFactoryを提供すればよい.
Converterインタフェースは次のとおりです.
public interface Converter<F, T> {
@Nullable T convert(F value) throws IOException;
/** Creates {@link Converter} instances based on a type and target usage. */
abstract class Factory {
/**
* Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for
* response types such as {@code SimpleResponse} from a {@code Call}
* declaration.
*/
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
* values.
*/
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Field @Field}, {@link FieldMap @FieldMap} values,
* {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
* {@link Query @Query}, and {@link QueryMap @QueryMap} values.
*/
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
/**
* Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
* example, index 1 of {@code Map} returns {@code Runnable}.
*/
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
/**
* Extract the raw class type from {@code type}. For example, the type representing
* {@code List extends Runnable>} returns {@code List.class}.
*/
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}