一、介绍
Retrofit,是一个网络框架。客户端创建一个Retrofit 实例,建造者设计模式,配置一些基础内容,例如baseUrl地址,CallAdapter工厂,Converter工厂,okhttp3的Call工厂,底层网络访问默认okhttp3网络框架。
Retrofit retrofit = new Retrofit.Builder().baseUrl(HostIp)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build();
baseUrl方法,配置服务器Url。client方法,参数实现okhttp3.Call#Factory接口,工厂创建okhttp的RealCall对象,真正的网络请求由它发起。
Retrofit框架基于动态代理实现,定义一个接口,每一个接口方法描述一个Http请求。
private RestfulApi apiService;
//接口
public interface RestfulApi {
@POST("login?")
Call postLogin(@QueryMap Map paramMap);
}
//创建动态代理对象
apiService = retrofit.create(RestfulApi.class);
//调用代理对象方法,创建一个请求
Call call = apiService.postLogin();
//发起请求和回调
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
方法注解,@POST,@PUT,@GET,@DELETE,@HEAD,代表请求类型,参数注解,@Query,@QueryMap,@Field,@FieldMap,@Path,@Url,代表请求参数。
@GET请求,使用@Query或@QueryMap,参数拼接在Url路径后面。
@POST请求,使用@Field、@FieldMap和@FormUrlEncoded,参数放在请求体。
根据interface接口,创建动态代理对象,客户端使用该对象,调用接口方法,返回一个Retrofit框架的Call或Rx的Observable。根据Call的同步/异步方式,发起请求,enqueue/execute回调,或者利用Rx的subscribe方法。
CallAdapter工厂,生产适配Call的CallAdapter,调用方法返回类型转换。Convert工厂,生产Response和Request的数据转换器。
二、Retrofit 和 Okhttp
Retrofit类的create方法,创建接口的动态代理对象。
public T create(final Class service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(),
new Class>[] { service }, new InvocationHandler() {
//该对象传入$Proxy0的构造方法中
private final Platform platform = Platform.get();
@Override
public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
...
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
调用代理对象的方法时,在InvocationHandler的invoke方法中拦截,根据Method载入一个ServiceMethod对象,以前调用过接口方法的ServiceMethod保存在Cache中,ServiceMethod服务于对应Method。
创建一个实现Retrofit#Call接口的OkhttpCall,callAdapter适配成接口返回对象Call或Rx的Observable,OkhttpCall封装调用方法的ServiceMethod和args参数,内部rawCall,okhttp3的Call类型。
调用OkhttpCall的enqueue或execute方法时,createRawCall方法,创建rawCall。
private okhttp3.Call createRawCall() throws IOException {
//解析参数,创建okHttp3#Request
Request request = serviceMethod.toRequest(args);
//工厂创建rawCall
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
...
return call;
}
ServiceMethod类解析参数数组,转换成一个Http协议的okHttp3#Request请求实体。okhttp3的Call工厂根据Request实体,创建okhttp3#Call,本质是RealCall。
@Override
public void enqueue(final Callback callback) {
okhttp3.Call call = rawCall = createRawCall();
...//入参是Retrofit的Callback
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response response;
try {
//转换Response
response = parseResponse(rawResponse);
} catch (Throwable e) {
callback.onFailure(OkHttpCall.this, e);
return;
}
callback.onResponse(OkHttpCall.this, response);
}
//同理,onFailure回调
...
});
}
OkhttpCall的enqueue方法,本质是调用内部okhttp3的enqueue方法,在回调对象okhttp3#Callback,调用Retrofit的#Callback方法。将okhttp3的Response转换Retrofit的Response。
Response parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
...
//NoContentResponseBody和ExceptionCatchingRequestBody都继承ResponseBody。
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
//新建一个Retrofit#Response
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
catchingBody.throwIfCaught();
throw e;
}
}
解析okhttp3#Response转换成Retrofit#Response,获取okhttp3.Response的ResponseBody,转换泛型body类型。
最终转换的Retrofit#Response包含T类型body和新生成okhttp3#Response,它内部是NoContentResponseBody。
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
转换器解析okhttp3的ResponseBody,配置不同的转换器工厂,Http协议一般使用GsonConverter数据转换器。
在ServiceMethod创建时,初始化responseConvert转换器,根据方法注解和返回实体类型responseType,调用Retrofit的nextResponseBodyConvert方法查找。
遍历工厂列表每一项Factory,调用工厂实现的responseBodyConverter方法,根据返回类型和注解获取匹配的Converter。
public interface Converter {
T convert(F value) throws IOException;
//创建Converter的抽象工厂
abstract class Factory {
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
public Converter, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
public Converter, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
}
}
将responseBody解析成我们期望的数据,只需要配置相应的工厂即可,如gson,xml,protobuf,需要在gradle中引入他们的jar包。
GsonConverter,负责解析responseBody对象,将json格式转换成用户自定义的实体对象,即interface方法返回Call>中的泛型。
将T、okhttp3#Response封装一个新建Retrofit#Response对象。
三、CallAdapter 适配
在invoke方法最后一步,将OkHttpCall进行CallAdapter适配,转换成接口方法调用方定义的Object。
public interface CallAdapter {
Type responseType();
T adapt(Call call);
//创建CallAdapter的工厂
abstract class Factory {
public abstract 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);
}
}
}
适配目的是接口方法返回对象可以是Retrofit#Call外的其他类型,适应不同的接入框架,如Guava,Java8,RxJava。
通过适配器工厂配置不同的适配器,前面添加Rx的工厂,可以适配Rx返回Observable类型。
初始化时,ExecutorCallAdapterFactory默认工厂。
private final List adapterFactories = new ArrayList<>();
List adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
在ServiceMethod创建时,初始化内部CallAdapter。
private CallAdapter createCallAdapter() {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
根据方法返回值类型和注解,调用Retrofit的nextCallAdapter方法查找。
public CallAdapter> nextCallAdapter(...) {
..
for (int i = start, count = adapterFactories.size(); i < count; i++) {
//每个工厂都实现了get方法,根据此刻调用方法的返回类型。
//在get方法中会有判断是否匹配,成功匹配,将返回对应是适配器。
CallAdapter, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
}
每个工厂都实现get方法,遍历工厂列表每一项Factory,根据方法返回类型和注解匹配获取CallAdapter,Call类型匹配默认ExecutorCallAdapterFactory工厂。
@Override
public CallAdapter> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//返回类型是Call。
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call adapt(Call call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
默认工厂创建的CallAdapter,adapt适配方法,将OkhttpCall再次封装,委派者设计模式,最终返回给接口方法调用者的Call是ExecutorCallbackCall。
@Override
public void enqueue(final Callback callback) {
..//delegate是OkHttpCall。
delegate.enqueue(new Callback() {//Retrofit#Callback
@Override public void onResponse(Call call, final Response response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
callback.onFailure(...);
} else {
//callback是用户传入
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
//同理,onFailure回调
...
});
}
接口方法调用者触发Call的enqueue异步方法,网络请求时,内部委派给OkHttpCall。
回调时,MainThreadExecutor的execute方法,通过内部绑定主线程Handler发送Runnable,将Callback执行权转移到主线程。
回调callback接收的Response是在OkHttpCall中已经okhttp3#Response转换过的Retrofit#Response。
适配目的是将Callback发送到主线程。通过它发起网络请求,不用操心线程切换啦。
四、Retrofit 和 Rx
RxJava2CallAdapterFactory工厂,Call适配器是RxJava2CallAdapter,将Retrofit#Call转换成Observable类型。
@Override
public CallAdapter, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class> rawType = getRawType(returnType);
...
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;
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
工厂get方法,判断匹配类型Observable、isFlowable或者isSingle。
Observable postRxLogin(@QueryMap Map paramMap);
调用interface的postRxLogin方法时,在invoke方法,ServiceMethod内部的callAdapter是RxJava2CallAdapterFactory生产的RxJava2CallAdapter。
@Override public Object adapt(Call call) {
//入参call是Retrofit的Call。
Observable> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {//是isBody。选择BodyObservable。
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
...
return observable;
}
创建一个CallExecuteObservable,包含原始Retrofit#Call,即转换前的OkhttpCall,返回Observable是BodyObservable。
我们最终返回的Observable就是BodyObservable对象,在DataModel数据源,通过subscribeOn将被观察者放到子线程,网络请求,observeOn让观察者在主线程,回调。
public Observable getRxLogin() {
return api.postRxLogin(xxxx登陆参数)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
最终postLogin方法返回BodyObservable,设定subscribe方法在子线程工作。
public final Disposable subscribe(Consumer super T> onNext, Consumer super Throwable> onError) {
return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer());
}
调用#subscribe方法,参数自定义Consumer,最后,调用Observable类的抽象方法subscribeActual,BodyObservable子类实现它。
@Override
protected void subscribeActual(Observer super T> observer) {
upstream.subscribe(new BodyObserver(observer));
}
upstream是内部委托类,CallExecuteObservable。向他注册subscribe一个观察者BodyObserver,封装外部Observer。
同样,最后进入CallExecuteObservable的subscribeActual方法,这里是真正进行网络请求的地方。调用Retrofit#Call#execute方法,此时,已经在子线程中,使用execute方法。
通过Retrofit#OkhttpCall获取Response,通过观察者BodyObserver的onNext和onComplete方法,调用封装外部Observer的同样方法。最终,通知到Consumer,在主线程回调。
使用RxJava这一套异步框架本质其实和前面默认工厂的ExecutorCallbackCall目的是一样的,实现子线程请求,主线程回调。用户调用interface接口网络请求方法流程图。
五、总结
基于interface设计,动态代理模式生成interface对象,接口方法转换成一个Http请求实体。
每个接口方法有一个ServiceMethod类,注解解析,Response和Request转换。
支持Rx异步框架实现回调路由,根据接口方法返回的参数类型,决定使用的工厂类型,将Retrofit的Call适配成Rx的Observable。
数据解析工厂可配置,支持多种数据类型。
将数据解析和异步框架分离,可扩展,耦合度低。
任重而道远