Retrofit详解:新手学习

这是我在学习Retrofit时为了理解写下来的,写的很详细,如果你是对Retrofit不了解,请一定从头到尾耐心地读下来。

我在遇到一个方法是,常常会一直深入下去,所以往往结果就是深入结束后都忘记从哪儿开始的了,所以请耐心地回头看看。

> 一.创建Retrofit


 Retrofit retrofit=new Retrofit.Builder()
                 //指定地址,要以“/”结尾
                .baseUrl()
                //网络请求适配器工厂
                .addCallAdapterFactory()
                   //数据转换工厂
                .addConverterFactory()
                //回调执行器
                .callbackExecutor()
                //网络请求执行器工厂
                .client()
                .build()               

 

以上就是我们常见的Retrofit对象创建过程,接下来我们一步步看看这背后到底干了什么

    

1. new Retrofit.Builder()

很明显,Retrofit是通过建造者模式创建的,然后让我们看看源码。

public Builder() {
      this(Platform.get());
    }

调用了另一个有参数的构造函数

 

  Builder(Platform platform) {
      this.platform = platform;
    }

只是把Platfrom对象传入而已,所以重点就是Platform.get(),让我们来看看

 

private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

直接返回了一个静态常量,再来看看findPlatform()

 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();
  }

意思很明显了,就是判断当前的平台是什么。这里通过反射来判断,Clss.forName(String),如果有这个类名,说明就是在这个平台。因为Android也是使用的Java,所以先判断是不是在Android,再判断是不是Java。如果都不是就返回默认Platform对象。

这里的Class Java8和Android都是Platform的静态内部类,我们只看Android。

static class Android extends Platform {
    @IgnoreJRERequirement // Guarded by API check.
    @Override boolean isDefaultMethod(Method method) {
      if (Build.VERSION.SDK_INT < 24) {
        return false;
      }
      return method.isDefault();
    }

    //(1).callbackExecutor()
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    //(2).addCallAdapterFactory()
    @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
        @Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
      return Build.VERSION.SDK_INT >= 24
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
    }

    @Override int defaultCallAdapterFactoriesSize() {
      return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
    }
    //(3).addConverterFactory()
    @Override List<? extends Converter.Factory> defaultConverterFactories() {
      return Build.VERSION.SDK_INT >= 24
          ? singletonList(OptionalConverterFactory.INSTANCE)
          : Collections.<Converter.Factory>emptyList();
    }

    @Override int defaultConverterFactoriesSize() {
      return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
    }

大家只看我标上1,2,3的部分就行了,这里就对应开头,Builder过程中对应的属性,很明显了,如果你在前面没有指定这些,它就会加入这些默认属性。

然后在注意下(1),defaultCallbackExecutor() ,这里返回了一个MainThreadExecutor对象,这个类也是Platform的静态类,让我们看看。

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

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

很明显了,这里是利用了Handler,将一些操作从子线程放到主线程执行,再想到OkHttp返回的结果是在子线程,我们很容易知道,这个defaultCallbackExecutor作用就是将网络请求的结果送到主线程,进行UI更新等操作。

终于看完了Builder()过程,接下来让我们看看添加属性的过程。

 

2. build()之前添加的属性 

baseUrl()​​​​​​ 

首先还是直接看源码

 public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl));
    }

首先会检查baseUrl是否为空,如果为空就抛出异常,这里面很简单就不看源码了。然后让我们看看HttpUrl.get() 

 public static HttpUrl get(String url) {
    return new Builder().parse(null, url).build();
  }

这里是通过建造者模式,首先解析url,然后在返回一个HttpUrl对象,parse()过程太复杂了,就不看源码了。

HttpUrl.get(String)将我们传进入的网址转换成了一个HttpUrl对象,然后我们再看看有参数的baseUrl(HttpUrl)

public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

首先还是检查HttpUrl是否为空,然后我们看它抛出的异常,"baseUrl must end in / ",说明我们传入的地址必须是以“/”结尾的,这个大家要注意。

 

addCallAdapterFactory()、addConverterFactory()

 public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

这两个代码类似,都是把自定义的CallAdapterFactoryConverterFactory加入Builder里的对应集合内,而且这还表明我们可以添加很多个工厂对象。

callbackExecutor()

public Builder callbackExecutor(Executor executor) {
      this.callbackExecutor = checkNotNull(executor, "executor == null");
      return this;
    }

指定唯一的回调执行器,也就是最后的结果是返回到哪个线程。

client()

public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }

指定网络请求执行器工厂,我们发现网络请求执行器工厂是OkHttpClient,所以网络请求执行器也就是call。用过OkHttp的小伙伴肯定很熟悉,Call call=OkHttpClient. newCall(Request),然后call.execute()/.enqueue()发送网络请求。

 

3. build()

最后就到了通过Builder创建Retrofit对象的时候了。

public Retrofit build() {
        //检查baseUrl是否为空
        if (baseUrl == null)
            throw new IllegalStateException("Base URL required.");
        //传入builder的网络请求执行器工厂,如果未指定,则默认为OkHttpClient
        okhttp3.Call.Factory callFactory = this.callFactory;
        if (callFactory == null)
            callFactory = new OkHttpClient();
        /*
        设置回调执行器,如果未指定,Platfrom.defaultCallbackExecutor
        这里的platform在new Builder()时已经设置好,是Android,
        所以回调执行器就是MainThreadExecutor,主线程
         */
        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
            callbackExecutor = platform.defaultCallbackExecutor();
        }
        /*
        网络请求执行器的适配器工厂
        首先加入build()之前用户指定的callAdapterFactory
        然后再加入platfrom默认的,这里是Android,对于API>=24,
        会返回CompletableFutureCallAdapterFactory,否则返回ExecutorCallAdapterFactory
         */
        List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
        callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

        /*
        数据转换器工厂
        首先加入默认的BuiltInConverters,然后加入用户指定的
        最后加入platform也就是Android的converterFactory,对于API>=24,加入OptionalConverterFactory
        否则是个空集合
         */
        List<Converter.Factory> converterFactories = new ArrayList<>(
                1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
        converterFactories.add(new BuiltInConverters());
        converterFactories.addAll(this.converterFactories);
        converterFactories.addAll(platform.defaultConverterFactories());
        //获得合适的网络请求执行器的适配器工厂和数据转换工厂都是从头开始,所以前面的优先级高
        //最后返回一个Retrofit对象,传入之前配置好的变量
        return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
                unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

callbackExecutor、callAdapterFactory和converterFactory在之前的Android类中已经提供了默认的,所以,

对于唯一的callbackExecutor,默认是主线程执行器,

callAdapterFactory集合首先会加入用户自定义的,然后才是Platform默认的,

converterFactory集合首先要加入一个BuiltInConverters对象,然后才加入用户自定义的,最后才是默认的。

最后的unmodifiableList()返回一个只能读,不能修改的集合。

这样,我们就成功的得到了一个Retrofit对象

 

> 二.使用Retrofit

(1)首先我们随便创建一个数据类

public class JavaBean{

    }

(2)然后是网络请求的接口类

public interface AccessApi{
    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<JavaBean> getCall();
}

(3)然后创建接口AccessApi的实现类

AccessApi NetService = retrofit.create(AccessApi.class);

(4)最后得到网络请求执行器对象,类似于OkHttpClient.newCall()

Call<JavaBean> call = NetService.getCall();

这里肯定有人对第三步不熟悉,平常我们得到一个接口的实现,都是要先有个class,然后implements接口,实现它的方法,最后再实例化这个类,我们这也没有声明其他类啊,这么就能得到接口的实现对象?

这里就利用了动态代理的方法,如果请先百度,否则对后面内容的理解会有些阻碍。

让我们看看retrofitcreate(Class)方法

 public <T> T create(final Class<T> service) {
        //检查用户声明的接口是否合法:
        // 1.传入的Class对象必须是接口    2.接口不能继承其他接口
        Utils.validateServiceInterface(service);
        //是否提前加载缓存声明的方法,true则加载
        if (validateEagerly) {
            //给接口的每个方法的注解进行解析并得到一个ServiceMethod对象
            //以Method为key加入一个HashMap--serviceMethodCache中
            eagerlyValidateMethods(service);
        }
        //返回网络请求接口代理对象也就是接口T的实例化对象,T是AccessApi类
        return (T) Proxy.newProxyInstance(
                service.getClassLoader(),//动态生成接口的实现类
                new Class<?>[] { service },//动态创建实例
                new InvocationHandler() {//
                    //这里是Android
                    private final Platform platform = Platform.get();
                    private final Object[] emptyArgs = new Object[0];

                    @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                            throws Throwable {
                        // 如果该方法是来自Object的方法,直接调用,传入的对象是new InvocationHandler()
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        //Api<24直接返回fasle,否则判断其是否是默认方法,默认方法就是接口中default方法
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }
                        //通过
                        return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
                    }
                    }); 
}

首先是通过Utils.validateServiceInterface(Class)检查传入的接口类对象是否合法,让我们仔细看看

static <T> void validateServiceInterface(Class<T> service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
    // Android (http://b.android.com/58753) but it forces composition of API declarations which is
    // the recommended pattern.
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }

大家从异常就可以知道,isInterface()首先是检查传入的Class对象是不是接口,然后.getInterfaces()检查接口是否继承了其他接口。

总之就是,传入的Class对象必须是接口,而且不能继承其他接口。

我们再往下看

//是否提前加载缓存声明的方法,true则加载
        if (validateEagerly) {
            //给接口的每个方法的注解进行解析并得到一个ServiceMethod对象
            //以Method为key加入一个HashMap--serviceMethodCache中
            eagerlyValidateMethods(service);
        }

这是是否提前加载接口的所有方法。validateEagerly在build()之前可以通过.validateEagerly()指定

我们再看看eagerlyValitdateMethods(service)

private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

先获得当前平台对象,然后遍历接口的所有方法,如果不是默认方法,就通过loadServiceMethod()加载。

默认方法这里就不介绍了,大家自行百度,loadServiceMethod()这里也先不介绍了,后面遇到一起说。

让我们接着往下看

 //返回网络请求接口代理对象也就是接口T的实例化对象,T是AccessApi类
        return (T) Proxy.newProxyInstance(
                service.getClassLoader(),//动态生成接口的实现类
                new Class<?>[] { service },//动态创建实例
                new InvocationHandler() {//
                    //这里是Android
                    private final Platform platform = Platform.get();
                    private final Object[] emptyArgs = new Object[0];

                    @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                            throws Throwable {
                        // 如果该方法是来自Object的方法,直接调用,传入的对象是new InvocationHandler()
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        //Api<24直接返回fasle,否则判断其是否是默认方法,默认方法就是接口中default方法
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }
                        //通过
                        return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
                    }
                    }); 

这里就是最后的返回值,返回网络请求接口的代理对象,通过这个对象就可以调用接口中的方法。

@Override invoke()调用的时机是(4)

我们再看仔细些

 //这里是Android
                    private final Platform platform = Platform.get();
                    private final Object[] emptyArgs = new Object[0];

                    @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                            throws Throwable {
                        // 如果该方法是来自Object的方法,直接调用,传入的对象是new InvocationHandler()
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        //Api<24直接返回fasle,否则判断其是否是默认方法,默认方法就是接口中default方法
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }
                        
                        return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
                    }
                    }); 

如果你已经了解动态代理,你应该知到,代理对象每次调用接口中的方法都会调用invoke(),里面的参数:

proxy:调用方法的代理对象

method:调用的方法

method:方法参数

return:方法返回值

// 如果该方法是来自Object的方法,直接调用,传入的对象是new InvocationHandler()
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        //Api<24直接返回fasle,否则判断其是否是默认方法,默认方法就是接口中default方法
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }

这两部分就不用多说了,注释已经很仔细了,platform.isDefaultMethod()前面已经展示过源码了

接下来我们来看最重要的部分,之前 提前加载所有方法时也用到的

 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

不过这里是先创建一个ServiceMethod对象,然后调用对应的方法,invoke()我们先不看,先看看这个loadServiceMethod()怎么返回一个ServiceMethod对象

ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

这里很明显是通过serviceMethodCache这个concurrentHashMap作为缓存,key为method,value是Servicemethod。

如果之前的validateEagerly指定为true,我们就会通过eagerlyValitdateMethods(),把这个接口的所有方法都加载成ServiceMethod对象,然后储存到serviceMethodCache。当然,这也是通过loadServiceMethod()实现的。

如果没有提前加载,就通过ServiceMethod.parseAnnotations()将method加载成ServiceMethod,然后加到缓存中。这里考虑到可能会出现:A方法正在加载,又有人准备调用A方法,这时就会重复加载两次。所以这里加上了锁,如果有人正在加载,就等到加载完成后去缓存查看,如果没有再去加载。

让我们接下来重点看看ServiceMethod.parseAnnotations()

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

我们先不看第一行和最后一行,先看中间部分。

这一部分就是验证方法返回值的合法性,不能有无法解析的类型,也不能是void

首先我们获得了方法的返回值,然后调用Utils.hasUnreasolvableType()验证这个返回值,让我们看看这个方法

static boolean hasUnresolvableType(@Nullable Type type) {
        //返回值是普通的类,可以
        if (type instanceof Class<?>) {
            return false;
        }
        //返回值有泛型,例如List<String>
        if (type instanceof ParameterizedType) {
            //将其强制转化成ParameterizedType,参数化类型
            ParameterizedType parameterizedType = (ParameterizedType) type;
            //getActualTypeArguments得到泛型数组,这里是String
            //为了防止出现List<Map<String,Integer>>,使用递归
            for (Type typeArgument : parameterizedType.getActualTypeArguments()) {
                if (hasUnresolvableType(typeArgument)) {
                    return true;
                }
            }
            return false;
        }
        //泛型数组,例如List<String>[]
        if (type instanceof GenericArrayType) {
            //getGenericComponentType()去掉数组,得到List<String>
            return hasUnresolvableType(((GenericArrayType) type).getGenericComponentType());
        }
        //如果返回值就是泛型,比如 public T get();
        //这种情况下反射无法获得具体的类型,所以无法解析,返回true
        if (type instanceof TypeVariable) {
            return true;
        }
        //返回值是泛型统配符,例如 ? extends classA、?super classB
        //直接返回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);
    }

中间这块代码就是对返回值的合理性进行检验。

接下来让我们看看第一行代码

RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

从名字我们就知道,解析的是方法的注解,就是我们之前接口中写的。

public interface AccessApi{
    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<JavaBean> getCall();
}

很容易就能想到,这部分应该是判断GET还是POST,传入了retrofit,其中有baseUrl,那么应该也是要把网址组合一下。再看名字,RequestFactory,请求工厂,很明显是先把请求所需要的属性都传进去最后可以得到一个完整的请求。

再想想Okhttp的Request创建过程,这一块就相当于将请求创建完毕了。看看具体的代码吧。

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

又是建造者模式,先看看构造函数

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //方法注解,写在方法上头的
      this.methodAnnotations = method.getAnnotations();
      //方法参数类型
      this.parameterTypes = method.getGenericParameterTypes();
      //方法参数注解,写在参数前面的
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

初始化了一些属性,获得了一些信息。

再看看build()

RequestFactory build() {
      for (Annotation annotation : methodAnnotations) {
        //(1)
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(method,
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        //(2)
        parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError(method, "Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError(method, "Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError(method, "Multipart method must contain at least one @Part.");
      }
    return new RequestFactory(this);

这一部分就不细说了,看看(1)(2)就知道,这里对方法和方法参数注解进行了解析,然后返回了RequestFactory,这个RequestFactory有注解解析后得到的地址信息。

让我们再回到ServiceMethod.parseAnnotations(),讲了这么多都不知道从哪儿来的了。

中间部分讲过了,第一行也讲过了,现在让我们来看看最后一行。

return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);

这一部分就是最后创建ServiceMethod对象的地方,很明显HttpServiceMethod继承自ServiceMethod

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    //(1)
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    //(2)
    Type responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }
    //(3)
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

首先我们来看(1),这一部分就是创建一个网络请求适配器,根据什么来创建呢?根据之前Retrofit的网络请求适配器工厂和method

再看看createCallAdapter()

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method) {
    Type returnType = method.getGenericReturnType();
    Annotation[] annotations = method.getAnnotations();
    try {
      //1
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }

从1可以知道,这里是通过retrofit创建一个callAdapter,传入方法的返回值类型和注解信息。

再看看retrofit.callAdapter()

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

再往下看

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");
    //1
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
        //2
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    //分割线
    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

代码中的1部分就是首先找到传入的参数CallAdapterFactory在集合中的位置,然后从位置的下一个开始遍历,因为这里传入的是空,所以是从0开始的。

在代码2部分,传入返回值类型、注解和retrofit对象,看看这个工厂能不能生产出CallAdapter,如果可以就返回,如果不能就继续遍历。

分割线以下就说明都遍历完了,没有一个工厂能生产出符合要求的CallAdapter,这时候收集错误信息,抛出异常。

我们仔细看看代码2部分的,

get(returnType, annotations, this);

看看这个干了什么。

public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

只是个抽象方法,所以我们要看它的实现类中是怎么写的。这里我们找的是Android.defaultCallAdapterFactories(),就不再重复贴代码了,这里返回的是ExecutorCallAdapterFactory对象,我们看看它是怎么重写get()方法的。

@Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //检查返回值RawType是不是Call.class
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    //检查返回值中的泛型类型,也就是最后的response类型
    final Type responseType = Utils.getCallResponseType(returnType);
    //创建CallAdapter
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

首先检查返回值Type的RawType是不是Call.clas,不是就返回空,是才能继续。

List<? extends Runnable>的RawType是List。

让我们看看responseType到底是怎么得到的,首先看看Utils.getCallResponseType()

static Type getCallResponseType(Type returnType) {
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    return getParameterUpperBound(0, (ParameterizedType) returnType);
  }

首先要判断返回值是不是ParameterizedType,如果不是直接抛出异常。因为ParameterizedType代表类型有泛型,比如List<String>。网络接口方法的返回值常常是Call<JavaBean>,JavaBean就是我们需要的Response。

接下来再看看getParameterUpperBoun()

 static Type getParameterUpperBound(int index, ParameterizedType type) {
    Type[] types = type.getActualTypeArguments();
    if (index < 0 || index >= types.length) {
      throw new IllegalArgumentException(
          "Index " + index + " not in range [0," + types.length + ") for " + type);
    }
    Type paramType = types[index];
    if (paramType instanceof WildcardType) {
      return ((WildcardType) paramType).getUpperBounds()[0];
    }
    return paramType;
  }

参数index表示获得第几个泛型类型,传入的是0,表示只要第一个泛型类型。

这里还有个判断,如果泛型是List<? extends Call>,对于这种情况,getUpperBounds()[0],就是Call,而且只有一个。对于super,返回的就是Object。

如果只是个List<String>,直接返回String;List<? extends String>返回String;List<? super String>返回Object。总之就是返回上边界。

好了,我们终于弄懂返回值类型responseType是怎么来的了,让我们回到ExecutorCallAdapterFactory.get()

来看最后创建返回CallAdapter

 return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };

返回了一个匿名内部类,重写了两个方法。

public Type responseType()返回我们刚刚得到的类型,

public Call<Object> adapt(Call<Object> call),传入一个call,返回一个实现了Call接口的ExecutorCallbackCall对象。

构造方法第一个参数是回调执行器,在这里是主线程回调执行器,因为Android。这个adapt()我们先不往下讲了,后面还会遇到。

 

好了,这样ExecutorCallAdapterFactory.get()就返回了一个CallAdaper,然后我们就回到了Retrofit.nextCallAdapter()

再往上,我们就回到了Retrofit.callAdapter();然后是HttpServiceMethod.createCallAdapter;最后我们回到了HttpServiceMethod.parseAnnotations

 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    //(1)
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType();

    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }
    //(2)
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

这样我们就可以弄懂(1)处的两行代码了,中间检查异常不看了,直接到(2),看看是怎么创建responseConver的。

想想我们的CallAdapter怎么创建的:根据注解和返回值类型,遍历retrofit中的CallAdapterFactory集合,哪个工厂能创建就返回。

Converter的创建也类似。

  //HttpServiceMethod
  private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create converter for %s", responseType);
    }
  }
//Retrofit
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }


 public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    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;
      }
    }

这里我们拿BuiltInConverters作为例子

 @Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
      Type type, Annotation[] annotations, Retrofit retrofit) {
    if (type == ResponseBody.class) {
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    if (checkForKotlinUnit) {
      try {
        if (type == Unit.class) {
          return UnitResponseBodyConverter.INSTANCE;
        }
      } catch (NoClassDefFoundError ignored) {
        checkForKotlinUnit = false;
      }
    }
    return null;
  }

可以看到,默认的BuiltInConverter只能处理需要的网络请求返回值为ResponseBody类型的情况,具体的就不多说了。让我们回到HttpServiceMethod的

 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    //(1)
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType();

    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }
    //(2)
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
    //(3)
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

现在我们可以看(3)了,callFactory在这里默认是OkHttpClient,如果忘了可以回头看看。最后返回的是HttpServiceMethod对象,让我们看看它的构造方法。

private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
      CallAdapter<ResponseT, ReturnT> callAdapter,
      Converter<ResponseBody, ResponseT> responseConverter) {
    this.requestFactory = requestFactory;
    this.callFactory = callFactory;
    this.callAdapter = callAdapter;
    this.responseConverter = responseConverter;
  }

很简单,确定好requestFactory、callFactory、callAdapter和responseConverter。这里再说一遍,XXFactory就是为了创建前面的XX对象。

好了,我们最后的到了一个HttpServiceMethod对象,那么我们就应该回到ServiceMethod.parseAnnotations(),然后再回到Retrofit.loadServiceMehod(),最后就是Retrofit.create()里内部类方法invoke()

 @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.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //HttpServiceMethod.invoke(args != null ? args : emptyArgs);
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }

loadServiceMethod(method)最后的结果就是一个HttpServiceMethod对象,当然,这个重写的invoke()方法只有当返回的代理对象调用接口方法时才会调用,也就是这个时候:

Call<JavaBean> call = NetService.getCall();

动态代理如果不懂,还是百度吧。

当我们执行了这个方法后,就会调用

@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.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }

这些我们都讲过了,除了

 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

最后的invoke(),让我们看看这个方法背后又干了什么吧。

如果你直接点进去你会看到

abstract T invoke(Object[] args);

我们已经知道loadServiceMethod()返回的是HttpServiceMethod对象,而它又继承了ServiceMethod,所以我们直接去这里面看看invoke()是怎么实现的。

@Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }

首先创建了一个OkHttpCall对象,传入了

requestFactory:网络请求信息

args:方法参数

callFactory:默认是OkHttpClient

responseConverter:网络结果数据转换器

调用了callAdapter.adapt(),adapt()的作用就是将默认的OkHttpCall,转换成指定的Call。

我前面说过adapt()会在后面遇到,就是这里。这个callAdapter就是ExecutorCallAdapterFactory.get()里返回一个匿名内部类

 @Override public @Nullable 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);
      }
    };
  }

这个adapt()返回了一个ExecutorCallbackCall对象,传入的是接口回调器(这里默认是主线程)和OkHttpCall对象。

然后我们看看这个返回的ExecutorCallback对象是干什么的

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;
    }
/********/
}

可以看到实现了Call。所以我们

Call<JavaBean> call = NetService.getCall();

 得到的call就是这个ExecutorCallback对象。

 

接下来就分别看看它的同步和异步网络请求方法。

首先是execute()

 @Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }

执行者是传入的Call对象,也就是OkHttpCall对象。再看看这个类的execte()是怎么实现的

@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;
    
    synchronized (this) {
      //一个Call只能执行一次
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
      //好像是创建错误,没太搞懂
      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else if (creationFailure instanceof RuntimeException) {
          throw (RuntimeException) creationFailure;
        } else {
          throw (Error) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }

    return parseResponse(call.execute());
  }

前面很简单,检查是否执行过,是否有错误,然后创建一个rawCall。

 private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

很简单,想想OkHttp使用时是怎么得到Call的

Call call=okHttpClient.newCall(Request request)

最后返回call,这个call才是真正执行的call,外面的那些都是对这个的封装。

接下来是parseResponse(call.execute()),parseResponse()就是将网络请求回来的结果转换成自己当初指定好的类实例。

 

接下来我们讲究异步请求,先让我们回到ExecutorCallback.enqueue()

 @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);
            }
          });
        }
      });
    }

这里还是通过对象delegate,也就是传入的OkHttpCall,调用它的enqueue()。

然后通过callbackExecutor将最后的结果传递到主线程。

去看看OkHttpCall.enqueue()

@Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");
    okhttp3.Call call;
    Throwable failure;
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }
    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }
    if (canceled) {
      call.cancel();
    }
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }
      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

首先还是跟execute()一样,检查是否执行过,是否创建失败了,是否取消了,然后根据createRawCall()得到真正的请求执行器。

调用其enqueue()方法,通过回调执行器,将结果回调到主线程。

如果成功还要通过converter将数据转换成想要的对象。

 

好了,到了这里,Retrofit的就分析完毕了。

让我来简单梳理下Retrofit的主要结构。

主要是有这么几块:

Retrofit:主要是提供原材料(baseUrl和method)、工厂和回调执行器

  1. callFactory:创建真正Call的工厂,默认是OkHttpClient,client.newCall(Request)
  2. converterFactories:生产converter,将网络请求结果转换成目标对象,比如Json->Student对象
  3. callAdapterFactories:生产callAdapter
  4. callbackExecutor:接口回调执行器

ServiceMethod:根据原材料和工厂,生产出合适的零件(converter、callAdapter)

Call:组装好的产品,invoke()调用,内部所有的零件相互配合,返回处理后的结果。

呼,大概这些吧,如果有哪里错了,还望斧正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值