我爱编程Android技术知识Android开发

Retorfit源码学习

2018-04-16  本文已影响0人  TheTwo

Retorfit源码学习


一.什么是Retorfit

二.请求实例

1.创建retorfit实例

 private HttpClient() {
        client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .addInterceptor(new LogInterceptor())
                .build();
        retrofit = new Retrofit.Builder()
                .baseUrl(Constants.SERVER_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        apiService = retrofit.create(MedexApiService.class);

    }

2.定义接口

public interface MedexApiService {
    @FormUrlEncoded
    @POST("./")
    Observable<BaseResponse<Logindata>> login(@FieldMap Map<String, String> params);
}

3.客户端调用

    ...此处省略代码
    HttpClient.getInstance().
                 getMedexApiService().
                 login(ParamsTool.getParms(params))
    ...此处省略代码

一次请求就这么完美的执行了,配合rxjava简直爽的不要不要的。那么它内部是如何处理传递的参数,和拿到参数后如何去请求,拿到结果后如何转换为客户端定义的类型,转换类型后又如何包装成rxjava Observable的,带着一些列问题,我们去探探究竟。

三.源码分析

从上面例子已经看出创建Retorfit实例时,通过Builder设置一些参数,那么这些参数用来干什么的,有什么用,它内部又如何设置这些值。带着疑问我们来看看new Builder和Builder中设置的这些参数用来干什么。

1.builder初始化及一些set方法

  public Builder() {
      //调用Platform.get()
      this(Platform.get());
  }
  //Platform.class
  private static final Platform PLATFORM = findPlatform();
  //get方法调用findPlatform返回一个Platform 
  static Platform get() {
    return PLATFORM;
  }
 //可以看到findPlatform方法根据不同平台返回不同的Platform,那我们直接来看
 //new Android()这块
 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) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
 //Android继承自Platform
 static class Android extends Platform {
   //可以当作是用来线程切换的执行器
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    //默认的网络发射器,RxJavaCallAdapterFactory就是CallAdapter.Factory的具体工厂,如果外部不提供就用这个默认的,具体ExecutorCallAdapterFactory源码这里不做分析,只分析RxJavaCallAdapterFactory。
    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    //回调方法执行器,作用是用来线程切换的。
    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());
      //在Retorfit中默认是将okhttp请求的返回的数据切换到主线程中
      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
  //最终调用Builder的第二个构造方法,并且添加默认的数据转换器
   Builder(Platform platform) {
      this.platform = platform;
      converterFactories.add(new BuiltInConverters());
    }
   public Builder baseUrl(String baseUrl) {
      //检测url合法性
      checkNotNull(baseUrl, "baseUrl == null");
      //外部传进来的String url 转换为Okhttp中认可的HttpUrl
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      return baseUrl(httpUrl);
    }
   public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      //得到url的分片
      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;
    }
  //设置okhttpClient
  public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }
   //检查合法性并赋值给 Budiler中  callFactory
    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
    }
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
 //将HTTP响应主体转换为? 也就是我们代码中定义的类型
 public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
   //将代码中请求的类型转换为HTTP请求体
   //主要用于对Part、PartMap、Body注解的处理
    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }
    // 这里用于对Field、FieldMap、Header、Path、Query、QueryMap注解的理
    // Retrfofit对于上面的几个注解默认使用的是调用toString方法
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }

addCallAdapterFactory()

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
//根据方法返回类型和方法上定义的注解返回CallAdapter,具体的CallAdapter在RxJavaCallAdapterFactory 中内部类SimpleCallAdapter实现,这里只针对,定义接口中返回Observable<BaseResponse>来说明
public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,Retrofit retrofit);

最后我们来看下build完成构建后的代码

 public Retrofit build() {
      //检查是否设置了baseUrl
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      okhttp3.Call.Factory callFactory = this.callFactory;
      //检查是否设置了OkhttpClient,如果没有new一个
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //回调方法执行器是否为null,如果我们没调用set设置那么默认为null
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
      //生成默认的回调方法执行器,默认的回调方法执行器就是                      //MainThreadExecutor                   
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      //讲adapterFactories集合中添加的数据复制到新的集合中,adapterFactories添加是我们外部传进来的RxJavaCallAdapterFactory

      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);

//在新的集合中又添加一个默认的网络发射器具体请查看Android中的defaultCallAdapterFactory方法,那么网络发射器集合中目前有两个。第一个是 RxJavaCallAdapterFactory。第二个是默认的网络发射器。  
  
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      //上文中已经说明在Builder有参构造中已添加了一个默认的数据转换器,那么我们在外部又添加了一个GsonConverterFactory,那么这个转换器集合中有两个。第一个是默认的转换器,第二个是外部提供的GsonConverterFactory

      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

     //构造Retrofit实例,并且把Builder中设置的参数传递给Retrofit

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

上面我们大致说了下设置数据转换器(GsonConverterFactory)和设置网络发射器(RxjavaCallAdapter),以及默认的数据转换器(BuiltInConverters)和网络发射器(ExecutorCallAdapterFactory),那么接下来,讲分析Retorfit中的create方法了。

2.Retorfit的create方法都干了什么。

 public <T> T create(final Class<T> service) {
    //验证是否是接口
    Utils.validateServiceInterface(service);
    //是否提前预加载接口中的所有方法,并且缓存。可以通过Builder去set设置
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //创建代理类
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
          private final Platform platform = Platform.get();
//这个 invoke方法是在代理类调用最终对象的方法时,会调用此方法。
//proxy 是代理对象,method是被代理方法,args 被代理参数
 @Override 
 public Object invoke(Object proxy, Method method, Object... args)   throws Throwable {
    if (method.getDeclaringClass() == Object.class) {
     return method.invoke(this, args);
    }
    //默认值是false先不管(Platform类中是false,默认的Android继承于Platform,但是并没有去重写此方法,所以该方法返回false)

    if (platform.isDefaultMethod(method)) {
    return platform.invokeDefaultMethod(method, service, proxy, args);
    }
    //重点 1
    //解析method中的注解,得到注解中的参数。
    //初始化数据解析器,初始化网络发射器
    //ServiceMethod 可以说是封装了请求的所有参数。
    ServiceMethod serviceMethod = loadServiceMethod(method);
    //重点2 构建Okhttp请求,真正去请求网络的执行器。
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    //重点3 包装网络请求执行器交给网络发射器来操作。
    return serviceMethod.callAdapter.adapt(okHttpCall);
    }
   });
}

从以上分析可知到,当调用Retorfit中的create方法时,创建代理类,当调用接口中定义的方法时,其实就会调用代理类的 invoke 方法,在此方法中,Retorfit拦截并做了三件事。

  1. 解析代理方法中的method 注解 ,包括method上的注解和method参数注解,并做了相应的缓存,创建外部设置进来的数据解析器GsonConverterFactory.create(),和网络发射器RxJavaCallAdapterFactory.create()。
  2. 创建OkhttpCall 这个类是真正去执行网络操作的类。并且把封装好的解析器GsonConverterFactory.create(),和发射器RxJavaCallAdapterFactory.create()的ServiceMethod 和方法中的参数传递给它。
  3. 将创建的okhttpCall对象交给网络发射器来发射也就是我们在创建Retorfit时传进来的RxJavaCallAdapterFactory.create()
    那么接下来对上文标注的重点一一分析。

3.ServiceMethod 都干了什么。

 ServiceMethod serviceMethod = loadServiceMethod(method);

当调用loadServiceMethod 时,传递的是我们接口中定义的方法。LoadServiceMethod方法代码如下:

  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
      synchronized (serviceMethodCache) {
     //先在缓存中找,key是接口中定义的method,值是ServiceMethod 
      result = serviceMethodCache.get(method);
      if (result == null) {
       //如果没找到,那么就去构建一个,并且缓存
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

3.1 ServiceMethod.Builder(this, method)

将Retofit实例以及被代理方法传递给ServiceMethod中的Builder.

    public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //获取method上定义的注解
      this.methodAnnotations = method.getAnnotations();
      //获取method中参数类型
      this.parameterTypes = method.getGenericParameterTypes();
      //获取method中参数注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

再看.build()方法

      public ServiceMethod build() {
      //重点1.1 创建网络发射器
      callAdapter = createCallAdapter();
      //返回类型
      responseType = callAdapter.responseType();
      ...省略一些判断代码
      //重点1.2创建相应的数据转换器
      responseConverter = createResponseConverter();
      //遍历method上的的注解并解析
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
     ...省略一些判断
     //得到方法注解参数长度
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      //遍历方法注解参数并解析封装在parameterHandlers数组中
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
       ...省略代码
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ...省略代码
      //返回ServiceMethod实例
      return new ServiceMethod<>(this);
    }

针对上面创建ServiceMethod时,标注的重点看下

3.1.1 创建网络发射器
   private CallAdapter<?> createCallAdapter() {
      //获取method返回值类型
      Type returnType = method.getGenericReturnType();
      ...省略判断
      //获取method上的注解
      Annotation[] annotations = method.getAnnotations();
      try {
        //调用retrofit中的callAdapter
        return retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { 
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

接着看retrofit.callAdapter方法

  //内部调用nextCallAdapter方法
  public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
  
  public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
   ...省略判断
    //传入的skipPast是null那么adapterFactories.indexOf(skipPast)得到的是-1,
    //那么start就是0,也就是从0开始遍历我们刚开始在Builder构建出的网络发射器集合,
    //并且调用这个网络发射器集合的get方法把返回类型,和方法上的注解还有Retorfit传递过去。并且返回CallAdapter<?>接口。
    //由于RxJavaCallAdapterFactory实现了CallAdapter接口,
    //上文中也提到,通过Retorfit.Builder传递进来的RxjavaCallAdapter在集合的第一个,
    //所以我们着重看下,RxjavaCallAdapter.get()方法实现。

    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;
      }
    }
 ...省略代码
 }
 //RxjavaCallAdapter.java
 @Override
  public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);
    String canonicalName = rawType.getCanonicalName();
    boolean isSingle = "rx.Single".equals(canonicalName);
    boolean isCompletable = "rx.Completable".equals(canonicalName);
    if (rawType != Observable.class && !isSingle && !isCompletable) {
      return null;
    }
    ..省略一些判断方法,
    //因为这里我们只分析返回接口中定义的返回Observable
    CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType, scheduler);
    return callAdapter;
  }
  
  //可以看到调用了getCallAdapter()方法,继续看getCallAdapter()方法
  
  private CallAdapter<Observable<?>> getCallAdapter(Type returnType, Scheduler scheduler) {
    //根据返回的泛型type得到Observable中定义的泛型参数type
    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    //根据泛型参数type得到参数Class
    Class<?> rawObservableType = getRawType(observableType);
    //Observable中的泛型是否是Response
    if (rawObservableType == Response.class) {
      ...省略验证代码
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      return new ResponseCallAdapter(responseType, scheduler);
    }
     //Observable中的泛型是否是Result
    if (rawObservableType == Result.class) {
      ...省略验证代码
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      return new ResultCallAdapter(responseType, scheduler);
    }
    //由于我们给的例子是Observable中的泛型参数是我们自己定义的对象,
    //那么最终返回SimpleCallAdapter
    return new SimpleCallAdapter(observableType, scheduler);
  }
 

至此我们上文中标注的1.1重点已分析完,大致总结下:在ServiceMethod调用Builder时,调用了createCallAdapter,而createCallAdapter又调用了Retorfit中的callAdapter方法,callAdapter内部调用nextCallAdapter方法,再在nextCallAdapter方法中,遍历我之前在Retorfit构建的网络发射器集合,并调用其内部元素的get方法,由于我们设置的RxJavaCallAdapterFactory在集合的首位,所以,我们直接看RxJavaCallAdapterFactory的get方法,根据我们在代码中定义的返回值(Observable)以及返回值泛型(BaseResponse)最中调用了并返回了SimpleCallAdapter。那么至此,网络发射器具体的实现已找到,接着分析重点2.2。

3.1.2
private Converter<ResponseBody, T> createResponseConverter() {
     //获取方法上的
      Annotation[] annotations = method.getAnnotations();
     //返回retrofit中responseBodyConverter方法并把接口返回类型和方法上的注解传递给它
        return retrofit.responseBodyConverter(responseType, annotations);
        ...省略异常代码
}        

//Retorfit.java
 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }
 //最终调用 nextResponseBodyConverter方法
 public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] annotations) {
    ...省略合法性代码
    //因为skipPast传递的是null,那么start也是从0开始,
    //那么集合中第一个元素的BuiltInConverters,而BuiltInConverters实现了responseBodyConverter,由于其内部根据判断没有我们想要的返回类型,
    //所以最终返回null。接着遍历第二个元素,也就是我们外部设置进来的GsonConverterFactory中的responseBodyConverter方法,
    //最终返回GsonResponseBodyConverter这个对象。
    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) {
        return (Converter<ResponseBody, T>) converter;
      }
    }
    ...省略异常代码
  }

至此,构建ServiceMethod源码已分析完。根据上面分析ServiceMethod构建时,完成了网络发射器的创建和响应数据转换器的创建,以及方法上方法参数中的注解解析。所以,ServiceMethod是封装了网络请求的所有参数以及网络请求数据的转换和网络请求发射器。

4.创建OkHttpCall

  //把封装好的所有网络请求相关的数据转换器和网络发射器传递给OkHttpCall,以及方法中定义的参数。
 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
 
  //接着看OkhttpCall类中关键方法
   @Override 
   public synchronized Request request() {
    okhttp3.Call call = rawCall;
    //默认为null
    if (call != null) {
      return call.request();
    }

    try {
     //创建okhttpCall对象并调用okhttp的request方法
      return (rawCall = createRawCall()).request();
    } catch (RuntimeException e) {
      creationFailure = e;
      throw e;
    } catch (IOException e) {
      creationFailure = e;
      throw new RuntimeException("Unable to create request.", e);
    }
  }
  //创建okhttp3.Call
  private okhttp3.Call createRawCall() throws IOException {
   //内部通过ServiceMethod类中的方法构建一个Request
    Request request = serviceMethod.toRequest(args);
    //调用我们通过Retorfit Buidler传递进来的OkhttClient对象的newCall方法,创建okhttp3.Call
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }
  //就着看真正去请求的操作(这里我们只说同步请求)
    @Override 
    public Response<T> execute() throws IOException {
    okhttp3.Call call;
    synchronized (this) {
     ...省略判断
      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }
    if (canceled) {
      call.cancel();
    }
    //解析数据,拿到结果后最终会调用GsonResponseBodyConverter中的convert方法进行数据转换。
    return parseResponse(call.execute());
  }

至此OkhttpCall中请求和相应的代码已分析完。解析来看最后一步,也就是网络发射器代码。

5.网络发射器

上文中标注的重点3代码如下

serviceMethod.callAdapter.adapt(okHttpCall)

上面我们分析了ServiceMethod构建源码,所以我们知道这个callAdapter就是SimpleCallAdapter,那么直接看SimpleCallAdapter中的adapt方法源码。

 @Override 
 public <R> Observable<R> adapt(Call<R> call) {
      //创建Observable并发射CallOnSubscribe中的事件。
      Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) //
          .flatMap(new Func1<Response<R>, Observable<R>>() {
            @Override 
            public Observable<R> call(Response<R> response) {
              if (response.isSuccessful()) {
                return Observable.just(response.body());
              }
              return Observable.error(new HttpException(response));
            }
          });
      //默认为null      
      if (scheduler != null) {
        return observable.subscribeOn(scheduler);
      }
      return observable;
    }
  }
  //看看CallOnSubscribe中的实现
   static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> {
    private final Call<T> originalCall;
   //得到OkhttpCall的引用
    CallOnSubscribe(Call<T> originalCall) {
      this.originalCall = originalCall;
    }

    @Override public void call(final Subscriber<? super Response<T>> subscriber) {
      final Call<T> call = originalCall.clone();
      
     //把OkhttpCall加入到subscriptions集合中用于下面判断是否取消订阅
     //ubscriber.isUnsubscribed(),其实就是是否取消网络请求。
     //当客户端调用ubscriber.unsubscribed时,其实调用了call.cancel();
     
      subscriber.add(Subscriptions.create(new Action0() {
        @Override public void call() {
          call.cancel();
        }
      }));

      try { 
        //开始同步执行,所以如果接口中定义的是Observable返回的话,那么就会执行同步请求,
        //所以我们在代码中往往会写指定在子线程中发射事件,在主线程中消费时间,因为是同步请求嘛。
        Response<T> response = call.execute();
        if (!subscriber.isUnsubscribed()) {
         //调用onNext
          subscriber.onNext(response);
        }
      } catch (Throwable t) {
        Exceptions.throwIfFatal(t);
        //出现异常,那么调用onError
        if (!subscriber.isUnsubscribed()) {
          subscriber.onError(t);
        }
        return;
      }
     //最终调用onCompleted
      if (!subscriber.isUnsubscribed()) {
        subscriber.onCompleted();
      }
    }
  }

至此,Retorfit源码中主要流程分析完毕,关键分析点上面已标出,其他代码还是根据实际情况来分析,如果客户端没有用到rxjava+Retorfit,用Retorfit自带的Call,那么分析流程就不一样了,或者用到其他数据转换器,亦或者,接口中定义的不是Observable,而是Completable或者Single。

上一篇下一篇

猜你喜欢

热点阅读