拆Retrofit2.0 的create()方法流程

微信公眾號: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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容