Retrofit

前面已经分析了OkHttp源码的调用流程,通常会搭配Retrofit一起使用。笼统地说,Retrofit只是一个适配器,它内部封装了OkHttp,并不做实际的网络请求工作,而主要是为客户端调用网络请求和返回数据做适配,因此,我们说Retrofit只是一个适配器框架。同样的,先看下它的使用方法。

public interface RetrofitService {
    @GET("users/{user}/repos")
    Call> listRepos(@Path("user") String user);
}
     Retrofit retrofit = new Retrofit.Builder()
                .baseUrl( "https://api.github.com/" )//网络请求根地址,必须有,且末尾带/
                .addConverterFactory( GsonConverterFactory.create() )//数据解析适配器
                .addCallAdapterFactory( RxJava2CallAdapterFactory.create() )//请求适配器
                .build();

    //获取接口对象
     RetrofitService retrofitService = retrofit.create( RetrofitService.class );

      //获取OkHttpCall
     Call repos = retrofitService.listRepos( "XXX" );

     //同步请求
        try {
            Response execute = repos.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

      //异步请求
     repos.enqueue( new Callback() {
            @Override
            public void onResponse(Call call, Response response) {

            }

            @Override
            public void onFailure(Call call, Throwable t) {

            }
        } );

从示例看到,Retrofit只是做接口解析封装,这里的Call是Retrofit实现的一个装饰类,叫OkHttpCall,它持有OkHttp的Call ,即RealCall,由RealCall来做实际的网络请求。

下面我们先分析Retrofit的构建过程。

 public static final class Builder {
    //平台,默认是Android
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    //基地址
    private @Nullable HttpUrl baseUrl;
    //数据适配器列表
    private final List converterFactories = new ArrayList<>();
    //请求适配器列表
    private final List callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;
   
    Builder(Platform platform) {
      this.platform = platform;
    }

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

    ......
  }

Retrofit也是用构建者模式进行创建的,它的Builder构造参数需传入一个Platform对象,这意味着,Retrofit不仅可以使用在Android平台,也可以使用在Java平台中。如果我们不传入指定平台,则会调用Platform.get(),它默认返回了Android对象。

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

  //获取默认平台
  static Platform get() {
    return PLATFORM;
  }
  
  //获取平台
  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      //使用Android平台
      if (Build.VERSION.SDK_INT != 0) {
          return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    //使用Java平台
    return new Platform(true);
  }

  //获取默认请求适配器列表
  List defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
    }

    //获取默认执行器
   @Nullable Executor defaultCallbackExecutor() {
    return null;
    }

  //Android平台
  static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }
    
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    
    static class MainThreadExecutor implements Executor {
      //主线程Handler
      private final Handler handler = new Handler(Looper.getMainLooper());

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

可以看到,Android是Platform 的静态内部类,并覆盖了defaultCallbackExecutor方法来,用于返回自己的Executor。而Android的Executor实现类是MainThreadExecutor,其本质是封装了主线程的Handler,来执行Runnable ,这表明,Retrofit是在主线程中执行的。

public static final class Builder {
   //封装baseUrl为HttpUrl对象
    public Builder baseUrl(String baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      //封装成HttpUrl,后进行检查
      return baseUrl(HttpUrl.get(baseUrl));
    }

    //对baseUrl进行判断,并设置到成员变量
    public Builder baseUrl(HttpUrl baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      //获取片段列表
      List pathSegments = baseUrl.pathSegments();
      //最后一个字符必须是/
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

示例代码中,我们首先传入了基地址,它是必须设置的,并且字符串最后的“/”不能省略,否则会抛异常。

地址设置完成后,又调用了addConverterFactory传入数据适配器工厂GsonConverterFactory.create(),

public final class GsonConverterFactory extends Converter.Factory {

  //创建方法
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  //传入Gson 对象
  public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson);
  }

  //构造方法
  private GsonConverterFactory(Gson gson) {
      if (gson == null) throw new NullPointerException("gson == null");
      this.gson = gson;
    }
  ......
}

这里的逻辑比较简单,GsonConverterFactory 只是封装了 一个Gson对象。紧接着我们调用addCallAdapterFactory,设置了RxJava2CallAdapterFactory 适配器。

public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
  
  public static RxJava2CallAdapterFactory create() {
    return new RxJava2CallAdapterFactory(null);
  }

  private RxJava2CallAdapterFactory(Scheduler scheduler) {
    this.scheduler = scheduler;
  }

RxJava2CallAdapterFactory 继承了CallAdapter.Factory ,关于RxJava的原理将在<>中分析。

最终,构建时传入的参数都保留在Builder的成员变量中,Retrofit 会在buid方法中创建,并将参数传递过去,我们看Builder最后的build方法。

public static final class Builder {
  ......
  public Retrofit build() {
      //判断baseUrl不能为null
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      
      //不自己配置OkHttpClient,则new OkHttpClient()
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      
      //不实现自己的Executor ,则获取到MainThreadExecutor 
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 添加默认的请求适配器
      List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // 添加数据转换工厂
      List converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
      // 如果没有设置数据转换工厂则会使用默认的BuiltInConverters
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      //构建Retrofit
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

Retrofit构建完成后,则调用create方法获取接口对象。

public final class Retrofit {
  //缓存ServiceMethod
  private final Map> serviceMethodCache = new ConcurrentHashMap<>();
  // OkHttpClient
  final okhttp3.Call.Factory callFactory;
  //基地址
  final HttpUrl baseUrl;
  //将响应数据进行转换
  final List converterFactories;
  // 适配器工厂
  final List callAdapterFactories;
  // 线程执行器
  final Executor callbackExecutor;
  //是否要立即解析接口方法
  final boolean validateEagerly;

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List converterFactories, List callAdapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

    //通过动态代理创建具体的网络请求实体类
   public  T create(final Class service) {
      validateServiceInterface(service);
      return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          @Override public @Nullable Object invoke(Object proxy, Method method,
              @Nullable Object[] args) throws Throwable {
            // 如果是Object中的方法,则正常执行
           if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //如果是platform默认的方法则执行platform的方法
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //获取ServiceMethod执行invoke
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
   }

    //获取ServiceMethod
     ServiceMethod loadServiceMethod(Method method) {
      //从缓存获取
      ServiceMethod result = serviceMethodCache.get(method);
      if (result != null) return result;
      //缓存不存在,则调用parseAnnotations创建
      synchronized (serviceMethodCache) {
        result = serviceMethodCache.get(method);
        if (result == null) {
          result = ServiceMethod.parseAnnotations(this, method);
          serviceMethodCache.put(method, result);
        }
      }
      return result;
    }

  }

可以看到,Retrofit通过动态代理返回了接口代理对象,当我们调用接口方法时,将会执行代理类的invoke方法。

代理类的invoke里,前两个判断用来过滤Object类和Platform 的方法,我们通常不会调用到。而是调用到关键方法loadServiceMethod,它将根据接口方法的声明和返回类型,获取到一个ServiceMethod对象,并调用其invoke方法,这个ServiceMethod对象对应我们接口的返回类型。

Retrofit的成员变量serviceMethodCache以Method为key,value为ServiceMethod,对ServiceMethod进行缓存。因此loadServiceMethod会首先从缓存获取,如果缓存没有,则通过ServiceMethod的静态方法parseAnnotations来构建。

abstract class ServiceMethod {

  //获取ServiceMethod
  static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
    //解析接口,封装成RequestFactory 
    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);
  }

  abstract @Nullable T invoke(Object[] args);
}

ServiceMethod是抽象类,它的子类是HttpServiceMethod。获取ServiceMethod时,ServiceMethod会先解析接口方法,并封装成RequestFactory 对象,再传递给HttpServiceMethod子类。因此,我们来看RequestFactory的parseAnnotations方法是如何解析的。

final class RequestFactory {
  //通过Builder创建
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

  static final class Builder {
     ......
    final Retrofit retrofit;
    final Method method;
    final Annotation[] methodAnnotations;
    final Annotation[][] parameterAnnotationsArray;
    final Type[] parameterTypes;
    ......

    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //获取注解
      this.methodAnnotations = method.getAnnotations();
      //获取形参
      this.parameterTypes = method.getGenericParameterTypes();
      //获取形参的注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    RequestFactory build() {
      //遍历解析注解
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      //请求方法不能为空
      if (httpMethod == null) {
        throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

       ......

      //解析形参注解参数
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }

      ......
      //构建RequestFactory
      return new RequestFactory(this);
   }

通过对接口方法的注解、形参和形参注解的解析,RequestFactory对象便持有了接口声明的各参数,它们都以数组的形式保存了下来。

紧接着通过执行HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)方法,RequestFactory将被传递到ServiceMethod的子类HttpServiceMethod中。

abstract class HttpServiceMethod extends ServiceMethod {
  ......
  static  HttpServiceMethod parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType = Utils.getParameterLowerBound(0,
          (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }

    CallAdapter callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response)");
    }
  
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
          return (HttpServiceMethod) new SuspendForResponse<>(requestFactory,
          callFactory, responseConverter, (CallAdapter>) callAdapter);
    } else {
           return (HttpServiceMethod) new SuspendForBody<>(requestFactory,
          callFactory, responseConverter, (CallAdapter>) callAdapter,
          continuationBodyNullable);
    }
  }

  @Override final @Nullable ReturnT invoke(Object[] args) {
    //创建OkHttpCall
    Call call = new OkHttpCall<>(requestFactory, args, callFactory,  responseConverter);
    return adapt(call, args);
  }
  
  protected abstract @Nullable ReturnT adapt(Call call, Object[] args);

  static final class CallAdapted extends HttpServiceMethod {
     private final CallAdapter callAdapter;

    CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
        Converter responseConverter,
        CallAdapter callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override protected ReturnT adapt(Call call, Object[] args) {
      return callAdapter.adapt(call);
    }
  }

  static final class SuspendForResponse extends HttpServiceMethod {
    private final CallAdapter> callAdapter;

    SuspendForResponse(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
        Converter responseConverter,
        CallAdapter> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override protected Object adapt(Call call, Object[] args) {
      call = callAdapter.adapt(call);

      Continuation> continuation =
          (Continuation>) args[args.length - 1];
      
      try {
        return KotlinExtensions.awaitResponse(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }


 static final class SuspendForBody extends HttpServiceMethod {
    private final CallAdapter> callAdapter;
    private final boolean isNullable;

    SuspendForBody(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
        Converter responseConverter,
        CallAdapter> callAdapter, boolean isNullable) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
      this.isNullable = isNullable;
    }

    @Override protected Object adapt(Call call, Object[] args) {
      call = callAdapter.adapt(call);

      Continuation continuation = (Continuation) args[args.length - 1];

      try {
        return isNullable
            ? KotlinExtensions.awaitNullable(call, continuation)
            : KotlinExtensions.await(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }
  ......
}

HttpServiceMethod也是抽象类,它增加了adapt抽象方法。由CallAdapted、SuspendForResponse、SuspendForBody这3个内部类继承。

由继承关系知道,ServiceMethod的invoke,实际由HttpServiceMethod来实现,它会先创建了一个OkHttpCall,上面提到它是一个装饰类,是对RealCall的封装。

final class OkHttpCall implements Call {
  //接口参数对象
  private final RequestFactory requestFactory;
  //接口参数
  private final Object[] args;
  //OKHttpClient
  private final okhttp3.Call.Factory callFactory;
  //GsonConverterFactory
  private final Converter responseConverter;
  //是否取消请求
  private volatile boolean canceled;
  //原生call,即RealCall
  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;
  @GuardedBy("this")
  private @Nullable Throwable creationFailure;
  
  @GuardedBy("this")
  private boolean executed;

  OkHttpCall(RequestFactory requestFactory, Object[] args,
      okhttp3.Call.Factory callFactory, Converter responseConverter) {
    this.requestFactory = requestFactory;
    this.args = args;
    this.callFactory = callFactory;
    this.responseConverter = responseConverter;
  }

由上面分析知道,最终请求调用是通过OkHttp的RealCall来操作的,我们先来看同步请求的调用流程。

final class OkHttpCall implements Call {

  ......
  //同步请求
  @Override public Response execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      //将executed置为true
      executed = true;
      ......
      //首次调用rawCall为null
      call = rawCall;
      if (call == null) {
        try {
          //获取RealCall
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); 
          creationFailure = e;
          throw e;
        }
      }
    }
    //是否取消
    if (canceled) {
      call.cancel();
    }
    //解析ok返回的数据
    return parseResponse(call.execute());
  }

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

//解析响应数据
 Response parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    ......
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      //根据设置的数据解析器进行解析
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
          catchingBody.throwIfCaught();
      throw e;
    }
  }

通过OKHttpClient创建RealCall,来执行网络请求,这一部分的具体执行流程已在<>做了分析。而当最后一步的parseResponse方法被调用,OkHttpCall会根据我们传入的数据解析器,将响应的网络数据进行解析,并返回给我们的上层调用。再来看异步请求调用流程。

final class OkHttpCall implements Call {

  ......

  //异步请求
@Override public void enqueue(final Callback callback) {
    Objects.requireNonNull(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 {
        //获取RealCall
          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 response;
        try {
          //解析响应数据
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }

        try {
          //回调给客户端
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          throwIfFatal(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) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });
  }

异步请求和同步请求的流程大致相同,最终通过接口回调给上层应用。

你可能感兴趣的:(Retrofit)