Retrofit,一个比较流行的网络请求框架。
首先一张图看下
1、首先创建一个Retrofit对象,然后调用create创建一个网络请求对象,如此即可开始请求网络。
2、虽然Retrofit会有默认的返回数据格式,但是我们总会希望结果能够返回特定的格式,而不是在返回之后再进行数据格式转换,所以我们会使用自定义的CallAdapter和对应的Factory用于返回特定的数据类型、Convert和对应的Factory用于数据格式转换。
其中CallAdapter.adapt就是用来适配返回我们需要的数据类型;而Convert.convert就是用来将网络请求回调数据进行格式转换。
3、Call用于发起网络请求;Callback是请求回调,可以得到我们需要的数据。
4、Retrofit默认使用OkHttpClient进行网络请求,如果需要自定义OkHttpClient,可以在Builder.client中传入。
5、可以说Retrofit是非常强大的,扩展行非常高。以下为自定义请求回调类型LiveData,也是比较常用的类型。
class LiveDataCallAdapterFactory : CallAdapter.Factory() {
override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *>? {
if (getRawType(returnType) != LiveData::class.java) {
return null
}
val observableType = getParameterUpperBound(0, returnType as ParameterizedType)
val rawObservableType = getRawType(observableType)
if (rawObservableType != HttpResult::class.java) {
throw IllegalArgumentException("Type must be HttpResult")
}
if (observableType !is ParameterizedType) {
throw IllegalArgumentException("Response must be parameterized")
}
val responseType = getParameterUpperBound(0, observableType)
return LiveDataAdapter<Any>(responseType)
}
}
class LiveDataAdapter<T>(var responseType: Type) : CallAdapter<T, Any> {
override fun adapt(call: Call<T>): Any {
return object : LiveData<HttpResult<T>>() {
val flag = AtomicBoolean(false)
override fun onActive() {
super.onActive()
if (flag.compareAndSet(false, true)) {
call.enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) {
val result = HttpResult<T>()
result.code = 201
result.msg = t.localizedMessage
postValue(result)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
postValue(JSON.parseObject(JSON.toJSONString(response.body()), HttpResult::class.java) as HttpResult<T>)
}
})
}
}
}
}
override fun responseType(): Type {
return responseType
}
}
其实代码不多,可以参考Retrofit的代码,Retrofit已经有实现的默认转换器。
其中AtomicBoolean,保持原子性,保证高并发时只有一个线程访问它。
以下再看看大神提供的FastJsonConverterFactory代码
public class FastJsonConverterFactory extends Converter.Factory {
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return new FastJsonResponseBodyConverter<>(type, mParserConfig, featureValues, features);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return new FastJsonRequestBodyConverter<>(serializeConfig, serializerFeatures);
}
}
final class FastJsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private SerializeConfig serializeConfig;
private SerializerFeature[] serializerFeatures;
FastJsonRequestBodyConverter(SerializeConfig config, SerializerFeature... features) {
serializeConfig = config;
serializerFeatures = features;
}
@Override
public RequestBody convert(T value) throws IOException {
byte[] content;
if (serializeConfig != null) {
if (serializerFeatures != null) {
content = JSON.toJSONBytes(value, serializeConfig, serializerFeatures);
} else {
content = JSON.toJSONBytes(value, serializeConfig);
}
} else {
if (serializerFeatures != null) {
content = JSON.toJSONBytes(value, serializerFeatures);
} else {
content = JSON.toJSONBytes(value);
}
}
return RequestBody.create(MEDIA_TYPE, content);
}
}