retrofit2.4结合adapter-rxjava,converter-gson,源码解析
Retrofit作为时下android里比较常用的库,特别是结合着rxjava 后用起来很是酸爽啊,本篇就是剖析一下retrofit2.0结合adapter-rxjava,converter-gson后整个流程是怎样串起来的,以及源码的解析
先看下retrofit简介
retrofit基本使用这里不再赘述,直奔主题直接看源码了
retrofit源码地址 图一就是今天的重点了,图二是发起请求对应的注解种类了
都知道retrofit实际调用的是okhttp。也可以说retrofi就是在okhttp的基础上包了一层,通过大量的设计模式进行功能模块的解耦,使得整个整个流程变得整洁和清爽、
接口
阅读一个三方库 先从接口入手,先了解一下上层大致提供了哪些功能有助于快速理解
**Call **
对于okhttp 的call的的一个再包装,也是真正发出请求的对象接口
public interface Call extends Cloneable {
Response execute() throws IOException;
void enqueue(Callback callback);
boolean isExecuted();
void cancel();
Call clone();
/**返回的是okhttp的Request. */
Request request();
}
复制代码
**CallAdapter **
//可以把Call对象转化为另外一个对象,如Observable,Flowable
public interface CallAdapter {
//Type 返回值泛型的对象类型如:Flowable>里的Response
Type responseType();
//传入一个R返回一个T,T:返回值 一个Call或者Flowable
T adapt(Call call);
//工厂里提供三个方法 1:根据返回值returnType获取具体请求的CallAdapter 2:根据返回值type 获取泛型里的数据类型
// 3:通过type获取class的类型,获取整个返回值的类型 如Observable,Flowable ,Call
// 2,3 均为工具类
abstract class Factory {
//abstract抽象方法,一定要被实现
public abstract @Nullable CallAdapter, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
**Callback **
请求回调
**Converter **
数据转换适配器,可以对请求的数据或者响应的数据再度处理
public interface Converter {
T convert(F value) throws IOException;
/** Creates {@link Converter} instances based on a type and target usage. */
abstract class Factory {
/**
* 传入ResponseBody返回t,对响应数据进行解析,converter-gson会重写此方法
*/
public @Nullable Converter responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
/**
*
*传入T返回ResponseBody 对请求数据进行处理,只有在 申明@Body, @Part ,@PartMap
*这三个注解时才会生效
*
*/
public @Nullable Converter, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
/** *
* {@link Field @Field}, {@link FieldMap @FieldMap} values,
* {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
* {@link Query @Query}, and {@link QueryMap @QueryMap} values.
对以上注解的值进行处理 而已已经被BuiltInConverters(默认解析类)类重写,外部重写无效
*/
public @Nullable Converter, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
/**
工具类作用与CallAdapter里的一样
*/
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
复制代码
基本使用
获取 retrofit 实例以及添加上rxjava 请求适配器和converter-gson解析器
public Retrofit getRetrofit(String baseurl, OkHttpClient client) {
if (client == null)
client = getOkHttpClient();
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl(baseurl);//baseurl路径
builder.client(client)//添加客户端
.addConverterFactory(GsonConverterFactory.create());//添加Gson格式化工厂
//添加 rxjava
builder.addCallAdapterFactory(RxJava2CallAdapterFactory
.createWithScheduler(Schedulers.from(AppExecutor.instance())));
retrofit = builder.build();
return retrofit;
}
//自定义的通用解析类,t为data内具体对象,msg和code为公用数据部分
public class Response {
private T data;
private String msg;
private String code;
}
//定义接口类
public interface ApiService {
/**
* 测试数据
*/
@GET("data/福利/{num}/{page}")
Flowable> getGirlList(@Path("num") int num, @Path("page") int page);
}
//获取ApiService
ApiService apiservice=getRetrofit(baseurl,OkHttpClient).create(serviceClass)
//发起请求,(这里未经封装,正常使用要再封装下)
apiservice.getGirlList(1,2).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(new ResourceSubscriber>() {
@Override
public void onNext(Response o) {
//结果回调
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
})
复制代码
源码分析
Retrofit实例是使用建造者模式通过Builder类进行创建的
核心类
这里只关心Android平台下的java8的不看
static class Android extends Platform {
// Guarded by API check.
@Override
boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
/**
* ExecutorCallAdapterFactory默认工厂类,
* if (getRawType(returnType) != Call.class) {
* return null;}
*只解析返回类型为Call.class的数据,即原生retrofit的返回值都会使用这个工厂,原因后面
*/
@Override
List extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return singletonList(new ExecutorCallAdapterFactory(callbackExecutor));
}
/**
* android平台 默认为MainThreadExecutor,
*/
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
}
**默认CallAdapter实体类 提供了只解析解析返回Call.class类型的CallAdapter **
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override public @Nullable CallAdapter, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter
然后看下 GsonConverterFactory gson解析类 重写了responseBodyConverter和requestBodyConverter 实际都通过 gson 把返回数据或者请求数据解析成指定的type
public final class GsonConverterFactory extends Converter.Factory {
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
复制代码
**然后看下 RxJava2CallAdapterFactory rxjava适配器 实现get方法 只解析 返回类型为 Observable.class ,isFlowable , isSingle ,isMaybe四类
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
/**
* Returns an instance which creates synchronous observables that do not operate on any scheduler
* by default.
*/
public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null, false);
}
/**
* Returns an instance which creates asynchronous observables. Applying
* {@link Observable#subscribeOn} has no effect on stream types created by this factory.
*/
public static RxJava2CallAdapterFactory createAsync() {
return new RxJava2CallAdapterFactory(null, true);
}
/**
* Returns an instance which creates synchronous observables that
* {@linkplain Observable#subscribeOn(Scheduler) subscribe on} {@code scheduler} by default.
*/
public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJava2CallAdapterFactory(scheduler, false);
}
private final Scheduler scheduler;
private final boolean isAsync;
private RxJava2CallAdapterFactory(Scheduler scheduler, boolean isAsync) {
this.scheduler = scheduler;
this.isAsync = isAsync;
}
@Override
public CallAdapter, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + " or " + name + " extends Foo>");
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response or Response extends Foo>" );
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result or Result extends Foo>" );
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
}
复制代码
**继续 Retrofit 类核心方法 **
public T create(final Class service) {
Utils.validateServiceInterface(service);//service必须为接口类,且方法数>0
if (validateEagerly) {//validateEagerly 是否预解析service里所有方法注解,正常是使用一个方法才解析一个,然后放到缓存里,下次直接用缓存
eagerlyValidateMethods(service);
}
//动态代理,传入一个接口返回一个对象
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[]{service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//platform.isDefaultMethod(method) 平台下 痕为fasle,兼容java8的不关心
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
终于到重点 loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
复制代码
**先看 loadServiceMethod(method) **
核心方法 result = ServiceMethod.parseAnnotations(this, method);
static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
先看一下RequestFactory 类 通过解析注解 提供 okhttp3.Request(真正的请求)
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
private final Method method; // 调用的service内方法名字
private final HttpUrl baseUrl;
final String httpMethod; // 请求方法:get.post.put...
private final String relativeUrl;//实际的url: baseUrl+ 后缀默认
private final Headers headers;// 头信息
private final MediaType contentType;//contentType
private final boolean hasBody;// post方式才有
private final boolean isFormEncoded;//是否是表单提交
private final boolean isMultipart;//带文件的键值对提交
private final ParameterHandler>[] parameterHandlers;//这个类很重要,负责根据不同的注解类型 去把传入的参数和注解的value 做相应的拼接处理
//retrofit里关于注解的解析 都在Builder 里
static final class Builder {
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();//获取方法上的注解
this.parameterTypes = method.getGenericParameterTypes();//传入参数对应的类型
this.parameterAnnotationsArray = method.getParameterAnnotations();//参数注解,二维数组,每个参数上的注解都是数组
}
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
//确认请求方式 并对传入注解的value做校验,根据请求方式确定此次请求是否有body
parseMethodAnnotation(annotation);
}
//这里开始解析方法上的注解参数,可以有多个参数然后 每个参数上可以跟多个注解,所有是个二维数组,说是这样说,但是实际操作的时候 一个参数上只允许跟一个注解,多了会包错
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
}
return new RequestFactory(this);
}
}
}
复制代码
**看下 parseParameter() **
/**
* 解析参数注解
*
* @param p 当前参数的位置
* @param parameterType 参数对应的类型
* @param annotations 参数对应的注解,retrofit只允许有一个
* @return
*/
private ParameterHandler> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations) {
ParameterHandler> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
ParameterHandler> annotationAction =
parseParameterAnnotation(p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
//一个参数上只允许跟一个注解 多了会抛异常
if (result != null) {
throw parameterError(method, p,
"Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
}
if (result == null) {
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
复制代码
再看 parseParameterAnnotation()