【源码SOLO】Retrofit2源码解析(二)

442 阅读11分钟

版权声明:本文为博主原创文章,未经博主允许不得转载
Github:github.com/Darkwh
若有错误或疑问欢迎小伙伴们留言评论

友情提示!!!

本人英文渣,文章中哪些单词翻译的不够形象的话。。。。那你到是来打我呀O(∩_∩)O 另外本篇文章强烈建议打开源码参考阅读,否则造成强烈不适概不负责~

系列回顾

【源码SOLO】Retrofit2源码解析(一)

【源码SOLO】Retrofit2源码解析(二)

前言

上一篇为大家介绍了retrofit的使用和其中几个比较重要的类,本篇将会顺着retrofit的使用来详细分析源码。本文为了节省篇幅,代码中都添加了中文注释,这里我就讲一下我认为值得讲解的地方,小伙伴们记得看注释啊。那么接下来让我们正式开始吧!!

第一步:创建Retrofit对象

  val retrofit: Retrofit = Retrofit.Builder()
                  .addConverterFactory(GsonConverterFactory.create())
                  .baseUrl("http://gank.io/api/")
                  .build()

首先Retrofit采用建造者模式,这种模式大家应该都不陌生了,这里就不多介绍了。

addConverterFactory和baseUrl方法均是为builder的参数成员赋值,赋值之前会有一些非空或URL格式的检查,代码很简单。让我们直接聚焦到build方法中去:

        /**
         * Create the {@link Retrofit} instance using the configured values.
         * <p>
         * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
         * OkHttpClient} will be created and used.
         */
        public Retrofit build() {
            if (baseUrl == null) {
                throw new IllegalStateException("Base URL required.");
            }
            okhttp3.Call.Factory callFactory = this.callFactory;
            //如果未指定callFactory,则默认创建一个OkHttpClint来使用
            if (callFactory == null) {
                callFactory = new OkHttpClient();
            }

            Executor callbackExecutor = this.callbackExecutor;
            //如果未指定callbackExecutor,则获取默认的callbackExecutor
            if (callbackExecutor == null) {
                callbackExecutor = platform.defaultCallbackExecutor();
            }

            //做一次深度拷贝
            List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
            //此处将默认的CallAdapter放到集合末尾
            adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

            //做一次深度拷贝
            List<Converter.Factory> converterFactories =
                    new ArrayList<>(1 + this.converterFactories.size());

            //此处将默认的Converter.Factory实现添加到集合首位置
            converterFactories.add(new BuiltInConverters());
            converterFactories.addAll(this.converterFactories);
            //返回Retrofit实例
            return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
                    callbackExecutor, validateEagerly);
        }

在build的时候,callFactory、callbackExecutor未做显示指定的时候,都会采用默认的实现。而至于adapterFactories和converterFactories这两个集合变量,则分别将内置的实例添加到末尾和首位置。

获取默认实现的时候涉及到了Platform和BuiltInConverters这两个类,我们来看一下这两个类,首先来看Platform:

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
  ......
}

看下findPlatform方法,Android平台自然会返回Android这样一个Platform的子类

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

可以看到默认的CallbackExecutor为MainThreadExecutor,利用handler在回到主线程处理。默认的CallAdapterFactory为 ExecutorCallAdapterFactory

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
    final Executor callbackExecutor;

    ExecutorCallAdapterFactory(Executor callbackExecutor) {
      this.callbackExecutor = callbackExecutor;
    }

    @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<Object, Call<?>>() {
        @Override public Type responseType() {
          return responseType;
        }
  
        @Override public Call<Object> adapt(Call<Object> call) {
          return new ExecutorCallbackCall<>(callbackExecutor, call);
        }
      };
    }
}

ExecutorCallAdapterFactory提供一个匿名的CallAdapter实现,该匿名对象的adapt方法会返回ExecutorCallbackCall对象

static final class ExecutorCallbackCall<T> implements Call<T> {
  final Executor callbackExecutor;
  final Call<T> delegate;

  ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
    this.callbackExecutor = callbackExecutor;
    this.delegate = delegate;
  }

  @Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    delegate.enqueue(new Callback<T>() {
      @Override public void onResponse(Call<T> call, final Response<T> response) {
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            if (delegate.isCanceled()) {
              // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
              callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
            } else {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          }
        });
      }

      @Override public void onFailure(Call<T> call, final Throwable t) {
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            callback.onFailure(ExecutorCallbackCall.this, t);
          }
        });
      }
    });
  }
  ......
  @Override public Request request() {
    return delegate.request();
  }
}

静态代理模式,调用目标对象,即第一篇为大家介绍过的Call接口的内置实现OkHttpCall对象,并将通过接口将成功失败结果回调回来。

BuiltInConverters这个类我们放到后面去讲解。

第二步:创建自定义接口的代理对象

val service: TestService = retrofit.create(TestService::class.java)

create方法是整个Retrofit最精髓的一段代码,它的作用是通过Java的动态代理方式来返回一个你定义好的接口的动态代理对象,不明白动态代理的小伙伴们可以自行百度一下,网上有很多的讲解。看一下这段代码:

public <T> T create(final Class<T> service) {
        //检查接口,如果目标类不是一个接口或继承于其他的接口则抛出异常
        Utils.validateServiceInterface(service);
        //是否提前将method对象转换为ServiceMethod并缓存
        if (validateEagerly) {
            eagerlyValidateMethods(service);
        }
        //通过Java的动态代理返回代理对象
        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, @Nullable Object[] args)
                            throws Throwable {
                        // If the method is a method from Object then defer to normal invocation.
                        // 如果该方法属于Object的方法,则直接调用
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        // Android平台该if分支不会执行
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }
                        //将该方法映射为ServiceMethood
                        ServiceMethod<Object, Object> serviceMethod =
                                (ServiceMethod<Object, Object>) loadServiceMethod(method);
                        //创建OkHttpCall对象
                        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                        //利用CallAdapter将okHttpCall转换为指定的类型(默认为Call<Object>)
                        return serviceMethod.callAdapter.adapt(okHttpCall);
                    }
                });
    }

让我们将这段代码分开讲解

1.检查自定义的接口

Utils.validateServiceInterface(service);

对传入的自定义接口进行检查,如果该类并非一个接口或继承于另一个接口,则抛出异常。

2.是否提前将自定义接口中的方法都映射为ServiceMethod并缓存

      //是否提前将method对象转换为ServiceMethod并缓存
      if (validateEagerly) {
          eagerlyValidateMethods(service);
      }

可以通过Retrofit.Builder的validateEagerly方法来设置是否提前映射接口方法并缓存

3.创建并返回动态代理对象

//通过Java的动态代理返回代理对象
            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, @Nullable Object[] args)
                            throws Throwable {
                        // If the method is a method from Object then defer to normal invocation.
                        // 如果该方法属于Object的方法,则直接调用
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        // Android平台该if分支不会执行
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }
                        //将该方法映射为ServiceMethood
                        ServiceMethod<Object, Object> serviceMethod =
                                (ServiceMethod<Object, Object>) loadServiceMethod(method);
                        //创建OkHttpCall对象
                        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                        //利用CallAdapter将okHttpCall转换为指定的类型(默认为Call<Object>)
                        return serviceMethod.callAdapter.adapt(okHttpCall);
                    }
                });

首先如果调用的方法属于Object类的方法,例如notify,getClass等,则会直接调用。而第二个if在Android平台不会执行,参考Platform中代码,其invokeDefaultMethod方法总会返回false,最后代码会执行到最下面三行。让我们另起一个篇幅来看看这几行代码到底做了神马!!(第三步中讲解)

第三步:通过动态代理对象调用接口方法返回Call对象

    val call: Call<MsgBean> = service.getMsg()

在我们调用自定义接口的方法后,代码会进入到retrofit.create方法中的那个匿名InvocationHandler对象中的invoke方法中,一般情况下都会跳过前面两个if分支执行最下面的三行代码,并返回一个Call对象(上面说过了内置的Call对象为ExecutorCallbackCall)。来让我们一行行开始看看这几行代码到底做了什么:

    //将该方法映射为ServiceMethood
    ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);

调用loadServiceMethod方法并返回ServiceMethod对象,看下loadServiceMethod:

    ServiceMethod<?, ?> loadServiceMethod(Method method) {
        //首先从加载过的缓存列表中去取
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        //如果缓存过则直接返回
        if (result != null) return result;
        //双重锁,考虑到同步问题
        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                //通过ServiceMethod.Builder来创建ServiceMethod对象
                result = new ServiceMethod.Builder<>(this, method).build();
                //缓存到集合中
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }

loadServiceMethod方法会做这么几件事,首先从缓存列表中去获取缓存实例,如果未做缓存(即为null)则通过ServiceMethod.Builder来创建ServiceMethod,然后缓存并返回。serviceMethodCache的定义是这样子:

private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

ConcurrentHashMap是一个线程安全且拥有很好的并发写入能力的HashMap。

顺着代码我们继续分析ServiceMethod.Builder这个类,一下进入ServiceMethod分析

ServiceMethod

ServiceMethod.Builder

ServiceMethod.Builder拥有这么些个属性啊!! 再来看看构造方法:

    Builder(Retrofit retrofit, Method method) {
        this.retrofit = retrofit;
        this.method = method;
        this.methodAnnotations = method.getAnnotations();
        this.parameterTypes = method.getGenericParameterTypes();
        this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

ServiceMethod.Builder接收从外部传入的Retrofit(即第一步中你配置好的Retrofit对象)和Method(即你自定义接口中你说调用的那个方法的Method对象)两个参数,并通过method的getAnnotations、getGenericParameterTypes、getParameterAnnotations来分别为其成员属性初始化赋值。

继续看build方法:

        public ServiceMethod build() {
            //这里创建CallAdapter
            callAdapter = createCallAdapter();
            responseType = callAdapter.responseType();
            if (responseType == Response.class || responseType == okhttp3.Response.class) {
                throw methodError("'"
                        + Utils.getRawType(responseType).getName()
                        + "' is not a valid response body type. Did you mean ResponseBody?");
            }
            //这里创建Converter
            responseConverter = createResponseConverter();

            for (Annotation annotation : methodAnnotations) {
                //解析校验方法中的注解
                parseMethodAnnotation(annotation);
            }

            ......

            return new ServiceMethod<>(this);
        }

build方法中会创建CallAdapter和Converter实例(通过Retrofit中指定的CallFactory和ConverterFactory),校验方法上的注解和方法参数及参数注解。校验逻辑这里就跳过了,不难但是多,我们来重点看下CallAdapter和Converter的创建。

先看CallAdapter的创建

CallAdapter的创建

        private CallAdapter<T, R> createCallAdapter() {
            Type returnType = method.getGenericReturnType();
            //返回值校验
            if (Utils.hasUnresolvableType(returnType)) {
                throw methodError(
                        "Method return type must not include a type variable or wildcard: %s", returnType);
            }
            //返回值类型为Void抛出异常
            if (returnType == void.class) {
                throw methodError("Service methods cannot return void.");
            }
            Annotation[] annotations = method.getAnnotations();
            try {
                //看这里!!看这里!!看这里!!
                return (CallAdapter<T, R>) 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);
            }
        }

createCallAdapter中首先对方法的返回值进行校验,首先校验是否有无法处理的类型:

    //检查是否含有无法处理的类型
    static boolean hasUnresolvableType(Type type) {
        if (type instanceof Class<?>) {
            return false;
        }
        //判断返回值是否是泛型参数类型
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            for (Type typeArgument : parameterizedType.getActualTypeArguments()) {
                //此处递归检查
                if (hasUnresolvableType(typeArgument)) {
                    return true;
                }
            }
            return false;
        }
        if (type instanceof GenericArrayType) {
            return hasUnresolvableType(((GenericArrayType) type).getGenericComponentType());
        }
        //类型参数
        if (type instanceof TypeVariable) {
            return true;
        }
        //通配类型
        if (type instanceof WildcardType) {
            return true;
        }
        String className = type == null ? "null" : type.getClass().getName();
        throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
                + "GenericArrayType, but <" + type + "> is of type " + className);
    }

校验逻辑参考注释,hasUnresolvableType是一个递归方法,用于泛型层次比较深的情况。

其次返回值为void(无返回值)时也会抛出异常,经过以上两个检查后,最终调用retrofit.callAdapter(returnType, annotations),跟一下:

继续跟:

    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
                                             Annotation[] annotations) {
        checkNotNull(returnType, "returnType == null");
        checkNotNull(annotations, "annotations == null");
        
        //调用到这里时skipPast为null,因此start的值为0
        int start = adapterFactories.indexOf(skipPast) + 1;
        //遍历adapterFactories集合并调用get方法,如果不为null则返回
        for (int i = start, count = adapterFactories.size(); i < count; i++) {
            CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
            if (adapter != null) {
                return adapter;
            }
        }
        ......
        throw new IllegalArgumentException(builder.toString());
    }

nextCallAdapter会从adapterFactories的首位开始遍历并调用get方法,当找到能够处理当前调用方法的CallAdapter后便停止遍历并返回该CallAdapter,如果未找到合适的CallAdapter(包括内置的CallAdapter),则抛出异常。

再看Converter的创建

Converter的创建

        private Converter<ResponseBody, T> createResponseConverter() {
            Annotation[] annotations = method.getAnnotations();
            try {
                //看这里!!看这里!!看这里!!
                return retrofit.responseBodyConverter(responseType, annotations);
            } catch (RuntimeException e) { // Wide exception range because factories are user code.
                throw methodError(e, "Unable to create converter for %s", responseType);
            }
        }

直接看注释那里,继续跟!:

别停!再跟!:

    public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
            @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");
        //skipPast此时也为null,start的值为0
        int start = converterFactories.indexOf(skipPast) + 1;
        //遍历converterFactories,找到合适的(不为null)则返回
        for (int i = start, count = converterFactories.size(); i < count; i++) {
            Converter<ResponseBody, ?> converter =
                    converterFactories.get(i).responseBodyConverter(type, annotations, this);
            if (converter != null) {
                //noinspection unchecked
                return (Converter<ResponseBody, T>) converter;
            }
        }
        ......
        throw new IllegalArgumentException(builder.toString());
    }

和nextCallAdapter方法很相似,从converterFactories中遍历寻找合适的Converter,一旦找到则终止循环并返回,如果找不到合适的Converter则抛出异常。在Retrofit.Builder的build方法中有提到build的时候converterFactories会被添加一个内置的Converter到首位置。这个Converter是BuiltInConverters,现在让我们来看一下BuiltInConverters这个类的定义:

final class BuiltInConverters extends Converter.Factory {
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        //如果返回结果类型泛型参数为ResponseBody
        if (type == ResponseBody.class) {
            return Utils.isAnnotationPresent(annotations, Streaming.class)
                    ? StreamingResponseBodyConverter.INSTANCE
                    : BufferingResponseBodyConverter.INSTANCE;
        }
        //如果返回结果类型泛型参数为Void
        if (type == Void.class) {
            return VoidResponseBodyConverter.INSTANCE;
        }
        return null;
    }
    
    ......
}

这里只给大家贴出了responseBodyConverter这个方法的代码,可以看到当自定义接口中的方法的返回值泛型参数类型为ResponseBody时,如果有Streaming注解修饰则返回StreamingResponseBodyConverter,否则返回BufferingResponseBodyConverter;如果返回值泛型参数类型为Void,则返回VoidResponseBodyConverter;上面都不满足则返回null。

上面是对

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);

这一行代码的跟踪和分析,现在回到invoke方法中最下面的部分继续看剩余两行代码:

    //创建OkHttpCall对象
    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

创建OkHttpCall对象

    //利用CallAdapter将okHttpCall转换为指定的类型(默认为Call<Object>)
    return serviceMethod.callAdapter.adapt(okHttpCall);

利用serviceMethod中的callAdapter的adapt方法将内置的OkHttpCall转换为指定的类型

第四步:通过Call对象发起请求

        call.enqueue(object : Callback<MsgBean> {
            override fun onFailure(call: Call<MsgBean>?, t: Throwable?) {
                Log.i("wh", "onFailure")
            }

            override fun onResponse(call: Call<MsgBean>?, response: Response<MsgBean>?) {
                Log.i("wh", "onResponse")
            }

        })

使用内置的Call对象(ExecutorCallbackCall)发起请求,前面有将,这里就不在复述了。

至此本篇博客就结束了,写的不太好,希望能让各位看官有所收获,或许你在阅读Retrofit源码的时候帮助到你