In daily development, the common data transfer protocol format for network requests is usually fixed, such as JSON or XML. There are some exceptions, however, and having multiple formats in a project can be a headache for Android developers.
Retrofit-converter. Factory Conversion Factory
Retrofit is a common and powerful web request framework that converts a Bean to a RequestBody and a ResponseBody to a Bean via Converter. The official also provides some conversion factories for us to develop quickly: Retrofit-Converters
Importing dependent dependencies
implementation 'com. Squareup. Retrofit2: retrofit: 2.6.2'
implementation 'com. Squareup. Retrofit2: converter - gson: 2.6.2'
implementation 'com. Squareup. Retrofit2: converter - simplexml: 2.6.2'
Copy the code
The version number can be replaced with the latest version. Tip: SimpleXml has been officially deprecated and is officially recommended to use JAXB, but testing JAXB at the time reported errors. converter-jaxb
Create the ConverterFormat enumeration class
/** * How to parse data * JSON or XML */
enum class ConverterFormat {
JSON,
XML
}
Copy the code
Declare RequestConverter annotations
@Target(
AnnotationTarget.FUNCTION
)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class RequestConverter(val format: ConverterFormat = ConverterFormat.JSON)
Copy the code
The default format is JSON.
Declare ResponseConverter annotations
@Target(
AnnotationTarget.FUNCTION
)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class ResponseConverter(val format: ConverterFormat = ConverterFormat.JSON)
Copy the code
The default format is JSON.
Custom JsonOrXmlConverterFactory
class JsonOrXmlConverterFactory private constructor() : Converter.Factory(a){
private var jsonFactory: Converter.Factory
private var xmlFactory: Converter.Factory
init {
val gson = GsonBuilder()
.serializeNulls()
.create()
jsonFactory = GsonConverterFactory.create(gson)
xmlFactory = SimpleXmlConverterFactory.createNonStrict()
}
companion object {
fun create() = JsonOrXmlConverterFactory()
}
override fun requestBodyConverter(
type: Type,
parameterAnnotations: Array<Annotation>,
methodAnnotations: Array<Annotation>,
retrofit: Retrofit
): Converter<*, RequestBody>? {
for (annotation in methodAnnotations) {
if (annotation is RequestConverter) {
if (annotation.format == ConverterFormat.JSON) {
return jsonFactory.requestBodyConverter(
type,
parameterAnnotations,
methodAnnotations,
retrofit
)
} else if (annotation.format == ConverterFormat.XML) {
return xmlFactory.requestBodyConverter(
type,
parameterAnnotations,
methodAnnotations,
retrofit
)
}
}
}
return jsonFactory.requestBodyConverter(
type,
parameterAnnotations,
methodAnnotations,
retrofit
)
}
override fun responseBodyConverter(
type: Type,
annotations: Array<Annotation>,
retrofit: Retrofit
): Converter<ResponseBody, *>? {
for (annotation in annotations) {
if (annotation is ResponseConverter) {
if (annotation.format == ConverterFormat.JSON) {
return jsonFactory.responseBodyConverter(type, annotations, retrofit)
} else if (annotation.format == ConverterFormat.XML) {
return xmlFactory.responseBodyConverter(type, annotations, retrofit)
}
}
}
return jsonFactory.responseBodyConverter(type, annotations, retrofit)
}
}
Copy the code
If no annotations are found, the JSON format is used.
Method of use
- Create the Retrofit by adding the JsonOrXmlConverterFactory addConverterFactory instance
fun init() {
val retrofitBuilder = Retrofit.Builder()
.addConverterFactory(JsonOrXmlConverterFactory.create())
val retrofit = retrofitBuilder.build()
val apiService = retrofit.create(ApiService::class.java)
}
Copy the code
- Add annotations to the interface
@POST
@RequestConverter(ConverterFormat.XML)
@ResponseConverter(ConverterFormat.JSON)
@Headers("Connection: Close")
fun netRelayCtrl(@Url url: String, @Body bean: NetRelayCtrlBean): Observable<NetRelayCtrlResultBean>
Copy the code
Without RequestConverter and ResponseConverter annotations, JSON parsing is used by default. If there are mistakes, but also hope to correct.