Retrofit2源码解析

前面讲了几篇关于网络编程基础方面的文章,我们现在来看看一些有关网络的应用框架。本篇先来分析大名鼎鼎的Retrofit2,下一篇分析OKhttp3,这些都是我们Android开发经常使用的框架,现在我们就来看看它们的内部到底是怎么实现的。

对于Retrofit2,我们还是从其使用入手,一步一步来解析。

   Retrofit  retrofit = new Retrofit.Builder()
                    .baseUrl(url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(getOkHttpClient())
                    .build();
    IServerAPI api = retrofit.create(IServerAPI.class);
public interface IServerAPI {
    /**
     * 获取购物车信息
     */
    @GET("pronline/Msg?FunName@ordercart")
    Call getCartData();

}

第一步,不用多说,典型的建造者模式,通过给Builder的各个成员变量赋值,然后利用这些值来构建Retrofit对象,这样我们就得到了一个Retrofit的实例,一般这个实例是单例的。
第二步,调用create方法,获得请求的接口类对象,之后我们就可以通过这个对象调用其定义的方法来进行网络请求了。如下:

     Call< CartInfo > call = serverAPI. getCartData();
     requestServer(call, callback)

     /**
     * 请求网络
     * @param call 请求
     * @param iResponseCallback 回调
     */
    public void requestServer(Call call, final IResponseCallback iResponseCallback) {
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                if (response != null) {
                    T bean = response.body();
                    iResponseCallback.onSuccess(bean);
                }
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                iResponseCallback.onFailure(t);
            }
        });

    }   

是的,使用是如此的简单,但是这种简单往往都是通过高度封装为代价的。对于我们软件开发者来言,一个框架是否好,这个框架是否简单易用占了很重要的一部分。而Retrofit一个优势,就是简洁易用,它通过注解配置网络请求的参数,采用大量的设计模式来简化我们的使用。而且它的拓展性也做的相当的好,Retrofit的功能模块高度封装,高内聚低耦合,我们可以自定义自己想要的组件,比如说我们可以自己选择解析工具等。 除此之外,Retrofit还有诸如性能好,处理速度快,代码简化等优势,给足了理由让我们去尝试使用这款网络请求框架。

现在,我们先来分析一下在初始化Retrofit实例的时候,做了哪些事:

public static final class Builder {
    private Platform platform;
    private okhttp3.Call.Factory callFactory;
    private HttpUrl baseUrl;
    private List converterFactories = new ArrayList<>();
    private List adapterFactories = new ArrayList<>();
    private Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
      this.platform = platform;
      converterFactories.add(new BuiltInConverters());
    }

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

    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly);
    }
  }

Builder是Retrofit的一个静态内部类,源码如上图,这里省略了为其成员变量赋值的方法代码。可以看到先调用了Platform.get()获取当前对应的平台,这里我们主要看一下Android的平台代码:

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

    @Override 
    CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      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);
      }
    }
  }

Android平台复写了defaultCallbackExecutor方法,提供的执行器将任务放到主线程去执行的;另外也复写了defaultCallAdapterFactory方法,返回一个ExecutorCallAdapterFactory对象。回到Builder构造函数里,接着在converterFactories集合中添加了一个默认的内置转换器,它主要是用来对HTTP和对象之间的数据转换,比如我们前面在初始化Builder的时候调用了addConverterFactory(GsonConverterFactory.create()),目的是通Gson的方式来转换数据。

再来看Builder中的build方法,通过给baseUrl、callFactory、callbackExecutor、adapterFactories和converterFactories这几个成员变量赋值来构建Retrofit实例。

接下来,我们再来看看最重要的一个方法,就是这个create:

public  T create(final Class 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);
          }
        });
  }

该方法中,首先 Utils.validateServiceInterface(service),检查我们定义的接口类文件是否合法;然后通过validateEagerly判断是否需要将接口里面的方法一次性的先加载到内存中,如果不加,后面则通过单个调用来将其加入到内存,如果我们定义的接口方法多,并且有些接口不是经常用的话,可以不先加载,这样节约内存;接下来,就是一个动态代理的过程了,对我们定义的每一个接口方法进行拦截,在invoke方法中,首先判断如果调用的方法是在Object.class中声明的,则正常调用,我们在使用中,都是在自己的接口文件中声明的这些方法,所以,这个一般不走;接下来判断platform.isDefaultMethod(method),在Android平台中这个始终未false,所以也不走;看最后3行代码,首先loadServiceMethod(method),就是刚才说的将该方法加载进内存,来看一下这个方法源码:

  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

可以看出,先将该方法对象封装进ServiceMethod对象中,然后将此对象和方法保存到一个LinkedHashMap类型的serviceMethodCache变量中,这样以后调用同样的方法时,直接从缓存中去,节省时间。现在我们来看看ServiceMethod具体的封装过程:

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

public ServiceMethod build() {

      //主要代码

      callAdapter = createCallAdapter();

      responseType = callAdapter.responseType();
   
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      return new ServiceMethod<>(this);
    }

同样采取的是建造者模式,创建callAdapter、responseConverter,获取responseType,解析方法注解,解析参数。这里重点分析一下callAdapter,因为后面要用,来看看其具体过程:

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.callAdapter(returnType, annotations),跟过去:

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

    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(adapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

大致的意思就是遍历retrofit中的集合adapterFactories中的对象,通过returnType和注解调用get方法,找到对应的adapter,然后返回,adapterFactories我们在之前初始化retrofit的时候执行的是这句代码:

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      // Make a defensive copy of the adapters and add the default Call adapter.
      List adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

这里的platform是Android平台,在最初我们已经讲了Android平台覆写了defaultCallAdapterFactory方法,如下:


    @Override
    CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

所以Retrofit的callAdapter方法返回的adapter是ExecutorCallAdapterFactory对象中的get方法的返回值。也就是说serviceMethod.callAdapter指向的是ExecutorCallAdapterFactory对象中的get方法的返回值。

回到Retrofit的create方法中,接下来调用了OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args),将该方法和具体的参数值封装进一个OkHttpCall对象中;最后调用了serviceMethod.callAdapter.adapt(okHttpCall),由上面的分析得出,这里的serviceMethod.callAdapter就是ExecutorCallAdapterFactory对象的get方法返回值,看其源码:

  @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 new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

返回了CallAdapter的一个匿名对象,其adapt方法中返回的是ExecutorCallbackCall子对象,并且将callbackExecutor 和 call(前面的okHttpCall)封装了进去,再来看看ExecutorCallbackCall这个静态内部类:

static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

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

    @Override 
    public void enqueue(final Callback callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback() {
        @Override 
        public void onResponse(Call call, final Response 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 call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

    @Override 
    public boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override 
    public void cancel() {
      delegate.cancel();
    }

    @Override 
    public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override 
    public Call clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override 
    public Request request() {
      return delegate.request();
    }
  }

可以看到这个类里面的方法都是采用委托的方式,交给delegate去执行,这个delegate就是前面我们传入的OKHttpCall对象。

至此,Retrofit的create方法就分析完成,总结一下这个方法的过程:

1. 检查接口文件是否合法
2.判断是否需要预加载所有方法
3.动态代理拦截每个方法,在这里面由分为3个步骤:

3.1 初始化ServiceMethod,并和方法关联,缓存到内存中
3.2 将ServiceMethod和实际的参数值封装进OkHttpCall对象中
3.3 调用serviceMethod中callAdapter对象的adapt方法,获得ExecutorCallbackCall对象,并将OkHttpCall封装进去,返回此ExecutorCallbackCall对象。

现在,我们拿到了这个ExecutorCallbackCall对象后,就开始请求网络,同步调用其execute()方法,异步调用其enqueue(Callback callback)方法,由于是委托模式,我们直接看OkHttpCall的这两个方法:

@Override public void enqueue(final Callback callback) {
    if (callback == null) throw new NullPointerException("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) {
          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)
          throws IOException {
        Response response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

总的来说,就是先调用createRawCall方法创建okhttp3.Call对象,然后通过此对象去请求网络,完成之后回调处理方法。那么我们看一下createRawCall的源码:

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

首先调用ServiceMethod的toRequest方法,并将实际参数值传递进去,来构造一个HTTP请求对象;然后将此请求传递到serviceMethod.callFactory的newCall方法中,来构造一个okhttp3.Call ,这里的serviceMethod.callFactory是什么?我们看到在serviceMethod的构造方法中有这样一句代码:

ServiceMethod(Builder builder) {
    this.callFactory = builder.retrofit.callFactory();
    ...
  }

可以看出这里的callFactory就是Retrofit的callFactory方法的返回值,而在当初初始化Retrofit的时候是这样的:

public Retrofit build() {
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      ...
}

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

 public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
  }

所以,这里的callFactory指向的就是一个OkHttpClient对象,因此createRawCall()方法返回的okhttp3.Call就是OkHttpClient中newCall方法的返回值。进入这个方法:

@Override 
public Call newCall(Request request) {
    return new RealCall(this, request);
}

可以看到直接将请求封装进RealCall对象中返回,由此可以知道最后实际发起请求的就是RealCall这个对象。由于RealCall和OkHttpClient都是okhttp3框架里面的东西,这里放到下一篇去讲解。

最后总结一下,本篇讲了retrofit的具体请求过程,大致分为三步:
1.初始化retrofit,并根据实际需求配置retrofit
2.解析我们定义的接口文件及其方法信息
3.通过实际参数值构造HTTP请求对象,并交给RealCall去真正的执行请求。

本篇只是讲解一下请求过程,还有其它一些东西没有讲到,比如retrofit中的converterFactories转换器的具体转换过程,以及构造HTTP请求的具体过程,待以后有时间再行分析。

你可能感兴趣的:(Retrofit2源码解析)