微信公眾號:JueCode
Retrofit不用多介紹了,誰用誰知道。我在使用過程中會產生疑問:
1.聲明的接口NetService怎么經過create就能調用發起網絡請求?
2.接口中的方法可以返回Call,也可以返回其他類型,比如Observable,這之間有什么關系,或者經過怎樣的轉化過程?
帶著這兩個疑問去探索下create()方法的執行流程。下面是該方法的源碼,比較短我們直接粘貼過來:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override
public Object invoke(Object proxy, Method method, 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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
我們的第一個疑問有解了,在create中會通過Java動態代理的方式來處理對方法的調用問題。這樣說可能比較抽象,簡單舉個栗子,通過動態代理就會返回Call對象。
public interface MyService{
@Get("info")
Call<User> getUser();
}
重點是最后的三行代碼。
1. ServiceMethod serviceMethod =(ServiceMethod)loadServiceMethod(method);
ServiceMethod官方解釋:
Adapts an invocation of an interface method into an HTTP call
有四個重要的成員:
//封裝call,默認是okHttpCall
this.callFactory = builder.retrofit.callFactory();
//最著名的RxJava,默認是不支持,通過添加.addCallAdapterFactory(RxJavaCallAdapterFactory.create())增加對Obsevable的支持
this.callAdapter = builder.callAdapter;
//addConverterFactory(GsonConverterFactory.create())將服務器返回的response,提取出ResponseBody(json)轉化為User
this.responseConverter = builder.responseConverter;
// 負責解析API定義時每個方法的參數
this.parameterHandlers = builder.parameterHandlers;
2. okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall實現Call接口,主要會用到的方法execute和enqueue,一個同步一個異步。
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
可以看出,會通過createRawCall創建okhttp,創建過程先通過serviceMethod創建request,request傳入callFactory創建okhttp3.Call。最后通過okhttpCall調用execute,enqueue的調用過程類似,最后也是通過okhttp調用enqueue。
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
3. serviceMethod.callAdapter.adapt(okHttpCall)
有幾個概念需要注意下:
responseType:這個返回的是關注的類型,比如Call ,返回的是User的類型
returnType:這個是接口中方法的返回類型,比如Call那么返回的就是Call類型
public interface CallAdapter<T> {
Type responseType();
<R> T adapt(Call<R> call);
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);
}
}
callAdapter是接口public interface CallAdapter的實現類
serviceMethod中的callAdapter通過callAdapter = createCallAdapter()創建
private CallAdapter createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError("Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
return 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中根據returnType從adapterFactories(List adapterFactories = new ArrayList<>();)中得到callAdapter
public CallAdapter callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
…….
}
factories可以在初始化retrofit的時候添加,我們來看下默認的CallAdapter.Factory, 工廠模式,這個也是retrofit中大量使用的設計模式,在public interface Converter 接口中也會使用。DefaultCallAdapterFactory沒有多少代碼,重點看下get方法
1.默認的模式只支持Call這種returnType,所以一進來會判斷是不是Call.class。
2.記下來會根據renturnType來獲得responseType,也就是上面例子中Call中的User類型。
3.最后會new一個CallAdapter,因為默認的是支持Call這種returnType,因此在adapt方法中直接返回call。
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();
@Override
public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
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 call;
}
} ;
}
}
4.我們再簡單看看RxJava2CallAdapterFactory
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
......
@Override
public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class rawType = getRawType(returnType);
......
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,isSingle, isMaybe, false);
}
}
在RxJava2CallAdapter中,看到熟悉的adapt方法,方法會將call封裝成Observable,最后我們就可以快樂的使用RxJava
final class RxJava2CallAdapter implements CallAdapter {
@Override
public Type responseType() {
return responseType;
}
@Override
public Object adapt(Call call) {
Observable > responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
……
return observable;
}
}
當然還沒完,我們在深入到Observable中一探究竟,我們看下異步CallEnqueueObservable的例子。可以看到實際執行還是通過call.enqueue(callback)執行。
final class CallEnqueueObservable extends Observable {
private final Call originalCall;
CallEnqueueObservable(Call originalCall) {
this.originalCall = originalCall;
}
@Override
protected void subscribeActual(Observer>observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call call = originalCall.clone();
CallCallback callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
call.enqueue(callback);
}
private static final class CallCallback implements Disposable, Callback {
......
}
}
到這里我們對create()方法的分析過程就結束了,Retrofit是通過Java動態代理實現對接口方法的調用處理,通過解析方法的注解和參數封裝request,通過request去構造HttpCall,再根據CallAdapter Factory對Call進行代理,其實內部還是通過OkHttp的Call模式做實際工作。Retrofit中比較多的使用工廠模式,實現很好的解耦,很值得借鑒。這方面的文章可以借鑒http://www.lxweimin.com/p/45cb536be2f4。
謝謝!
擴展閱讀:
https://blog.piasy.com/2016/06/25/Understand-Retrofit/
http://blog.csdn.net/lmj623565791/article/details/51304204
歡迎關注公眾號:JueCode