美文网首页Android知识
拆Retrofit2.0 的create()方法流程

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

作者: juexingzhe | 来源:发表于2017-05-05 02:04 被阅读0次

微信公众号: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.jianshu.com/p/45cb536be2f4
谢谢!

扩展阅读:

https://blog.piasy.com/2016/06/25/Understand-Retrofit/

http://blog.csdn.net/lmj623565791/article/details/51304204

欢迎关注公众号:JueCode

相关文章

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

    微信公众号:JueCode Retrofit不用多介绍了,谁用谁知道。我在使用过程中会产生疑问: 1.声明的接口N...

  • Retrofit2 源码分析(二)

    接着上回,分析过使用Retrofit的流程后,本篇继续分析 Retrofit # create方法(文章末尾附有时...

  • RxJava创建订阅流程

    Observable创建和订阅流程 这里的创建和订阅不考虑操作符操作。 查看Observable的create方法...

  • RxJava2源码学习之一

    本篇文章的目的就是分析下面这段代码的执行流程。不究细节。 先上个图 Observable的create()方法 这...

  • RxSwift(4)-Observable序列的创建

    create 根据指定的订阅方法创建一个可观察序列 控制台输出: 这是创建可观察序列最基本的方法。流程可以在前几篇...

  • 2017-12-25周一拆书帮株洲幸福分舵活动复盘

    一、活动的目的 1、学习提高自信的方法; 2、学习三级拆书家的拆书流程和优点; 3、认识志同道合的小伙伴。 二、发...

  • Kubernetes 部署 Tomcat

    Tomcat部署流程 kubectl create deployment tomcat --image=tomca...

  • Retrofit+Okhttp+Rxjava项目应用

    Retrofit出来之后,就曾学习过它的使用方法,也做过简单Demo。但是这次在项目中应用Retrofit2.0的...

  • Map操作符

    从create -> map ->subscribe create()方法调用后返回ObservableCreat...

  • HDFS读写流程

    HDFS写流程写流程图片... 1.客户端通过对DistributedFileSystem对象调用create()...

网友评论

    本文标题:拆Retrofit2.0 的create()方法流程

    本文链接:https://www.haomeiwen.com/subject/ywkjtxtx.html