Retrofit源码解析

2020-08-24  本文已影响0人  houtrry

写在前面

retrofit源码版本2.4.0
前置知识: Java动态代理

从用法开始

代码来自https://www.jianshu.com/p/021a2c6e128b

public interface RetrofitService {

    /**
     * 获取快递信息
     * Rx方式
     *
     * @param type   快递类型
     * @param postid 快递单号
     * @return Observable<PostInfo>
     */
    @GET("query")
    Observable<PostInfo> getPostInfoRx(@Query("type") String type, @Query("postid") String postid);
}
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.kuaidi100.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
        .build();
RetrofitService service = retrofit.create(RetrofitService.class);
Observable<PostInfo> observable = service.getPostInfoRx("yuantong", "11111111111");
observable.subscribeOn(Schedulers.io()) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(new Observer<PostInfo>() { 

            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(PostInfo postInfo) {
                Log.i("http返回:", postInfo.toString() + "");
            }
        });

问题有三个:

源码梳理

Retrofit

Retrofit#create

  public <T> T create(final Class<T> service) {
    //检查service是否是接口类型, 并且service不允许继承其它接口
    Utils.validateServiceInterface(service);
      //是否提前加载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, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              //如果调用的是Object中的方法, 则直接调用该方法
              return method.invoke(this, args);
            }
            //是否是平台的默认方法
           //Platform是接口, 有Android和Java8两个实现类
            //上面的Platform.get()方法会判断当前的系统类型
            //之所以这么处理, 是因为像Java8那样, 接口中是支持默认方法的
            //如果是默认方法, 就直接调用
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //加载方法信息(方法参数/返回值类型/注解信息等)
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //生成OkHttpCall并调用执行
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

这里重点就是最后的三行方法.

Retrofit#loadServiceMethod

  //动态代理前面执行的这个方法
  //遍历service中的全部public方法执行loadServiceMethod
  private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

//serviceMethodCache缓存信息
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
//serviceMethodCache的类型是Map<Method, ServiceMethod<?, ?>>
//如果已经加载过, 就从serviceMethodCache取出直接返回
//这也就是执行eagerlyValidateMethods的意义
//提前加载
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

//保证线程按全
//这里是不是很像单例里的双检锁/双重校验锁(DCL)
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        //如果没加载过, 就创建ServiceMethod
        //ServiceMethod这里就是保存方法的各个信息
        result = new ServiceMethod.Builder<>(this, method).build();
        //缓存进serviceMethodCache
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

ServiceMethod

ServiceMethod.Builder<>(this, method).build()

    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //获取方法的注解信息, 注解可以有多个, 所以是数组
      //比如注解@Get @NotNull
      this.methodAnnotations = method.getAnnotations();
      //方法的参数类型
      this.parameterTypes = method.getGenericParameterTypes();
     //方法的参数中的注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    public ServiceMethod build() {
      //获取callAdapter 
      //注意这个方法, 该方法和问题2有关
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      //注意这个方法, 该方法和问题3有关
      responseConverter = createResponseConverter();

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

      //...各种检查

      //Builder模式
      //最终生成ServiceMethod, 将builder中的各个参数保存到ServiceMethod中
      return new ServiceMethod<>(this);
    }

看到这里我们大概可以看出, 接口Service中的方法信息被一一对应保存在了对应的ServiceMethod中.

ServiceMethod#adapt

现在回到Retrofit#create方法的最后, 我们调用了如下方法

            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //这里尤其要注意的是, adapt的参数是Call的实现类, OkHttpCall, 后面还要用到
            return serviceMethod.adapt(okHttpCall);

下面我们就来看看 ServiceMethod#adapt

  T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

ServiceMethod#adapt方法很简单, 就是调用了CallAdapter#adapt, 而CallAdapter是接口, 这个时候我们就需要来看看这个callAdapter到底是谁了

在ServiceMethod.Builder#build方法中, 我们创建了callAdapter

      callAdapter = createCallAdapter();
    private CallAdapter<T, R> createCallAdapter() {
      //拿到方法的返回值信息
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        //最终, 我们的callAdapter是在retrofit类中获取
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

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");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    //遍历callAdapterFactories, 一个一个去找
    //找到就返回
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
   //...
    //如果没找到, 输出异常信息
  }

如果我们看一下callAdapterFactories, 就会发现, 这个Map里的值正是我们在创建Retrofit的时候通过retrofit2.Retrofit.Builder#addCallAdapterFactory方法传进去的RxJavaCallAdapterFactory.create(), 该方法创建了RxJavaCallAdapterFactory, 也就是说, 通过retrofit2.adapter.rxjava.RxJavaCallAdapterFactory#get方法, 我们获取到了真正的CallAdapter

RxJavaCallAdapterFactory#get

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);
    boolean isSingle = rawType == Single.class;
    boolean isCompletable = rawType == Completable.class;
    //如果方法的返回值类型不是Observable, 也不是Single和Completable
    //就返回空
    //也就是不由RxJavaCallAdapter处理
    if (rawType != Observable.class && !isSingle && !isCompletable) {
      return null;
    }

    //最后, 返回的是RxJavaCallAdapter
    if (isCompletable) {
      return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
    }

    //...

    return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
        false);
  }

也即是, 真正的CallAdapter其实是RxJavaCallAdapter

RxJavaCallAdapter#adapt

现在我们重新回头来看retrofit2.ServiceMethod#adapt

  T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

我们知道了这里callAdapter是RxJavaCallAdapter, 参数call是OkHttpCall
所以我们来看RxJavaCallAdapter#adapt

  //注意, 这里, 也是问题2的关键
  @Override public Object adapt(Call<R> call) {
    //如果是异步方法, 就返回CallEnqueueOnSubscribe, 如果是同步, 就返回CallExecuteOnSubscribe
    OnSubscribe<Response<R>> callFunc = isAsync
        ? new CallEnqueueOnSubscribe<>(call)
        : new CallExecuteOnSubscribe<>(call);

    OnSubscribe<?> func;
    if (isResult) {
      func = new ResultOnSubscribe<>(callFunc);
    } else if (isBody) {
      func = new BodyOnSubscribe<>(callFunc);
    } else {
      func = callFunc;
    }
    Observable<?> observable = Observable.create(func);

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isSingle) {
      return observable.toSingle();
    }
    if (isCompletable) {
      return observable.toCompletable();
    }
    return observable;
  }
final class CallEnqueueOnSubscribe<T> implements OnSubscribe<Response<T>> {
  private final Call<T> originalCall;

  CallEnqueueOnSubscribe(Call<T> originalCall) {
    this.originalCall = originalCall;
  }

  @Override public void call(Subscriber<? super Response<T>> subscriber) {
    // Since Call is a one-shot type, clone it for each new subscriber.
    Call<T> call = originalCall.clone();
    final CallArbiter<T> arbiter = new CallArbiter<>(call, subscriber);
    subscriber.add(arbiter);
    subscriber.setProducer(arbiter);
    //这里, 执行了OkHttpCall#enqueue, 拿到返回值后, 通过arbiter发射出去
    call.enqueue(new Callback<T>() {
      @Override public void onResponse(Call<T> call, Response<T> response) {
        arbiter.emitResponse(response);
      }

      @Override public void onFailure(Call<T> call, Throwable t) {
        Exceptions.throwIfFatal(t);
        arbiter.emitError(t);
      }
    });
  }
}

以异步为例, 如果简单些, 可以如下

        Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<T> subscriber) {
                call.enqueue(new Callback() {
                    @Override
                    public void onResponse(Call call, Response response) {
                        subscriber.onNext(response);
                    }

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

到这里, 我们就可以回答问题2了.
Retrofit通过动态代理实现了接口中的方法, 在方法的最后, 使用了RxJavaCallAdapter#adapt方法来获取结果, 而RxJavaCallAdapter#adapt做的也就是通过Observable.create创建Observable, 在调用OkHttpCall#enqueue方法拿到返回的结果后, 通过Observable发射出去, 生成Observable的数据流. 这样就把生成的结果转成了Observable.

在上面的异步方法中, 我们实际上通过retrofit2.Call#enqueue来获取请求结果, 而这里的Call, 实际上是OkHttpCall, 所以, 我们来看下OkHttpCall#enqueue

OkHttpCall

OkHttpCall中有OkHttpCall#enqueue和OkHttpCall#execute, 分别对应异步方法和同步方法
我们这里只说OkHttpCall#enqueue

OkHttpCall#enqueue

    //如果callback为空, 抛出异常
    checkNotNull(callback, "callback == null");
    //...检查各个参数
    //这里, 才是真正的调用了Okhttp的enqueue方法
    //调用OkHttp的enqueue异步方法, 获取结果
    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) {
          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();
        }
      }
    });
  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    //...
     //解析返回结果
    //这里也是问题3的关键
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
        //解析结果
        //泛型解析
        //这里跟我们创建Retrofit的时候通过addConverterFactory(GsonConverterFactory.create(gson)对应
       T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

所以, 问题3就是, 在OkHttpCall中, 拿到返回结果后, 将结果交给创建Retrofit的时候通过addConverterFactory(GsonConverterFactory.create(gson)生成的对应的GsonConvert, 转成对应的对象

重新梳理

这里, 我们回国头来重新看

 public <T> T create(final Class<T> service) {
    //...
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            //...

            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }
  1. 首先通过动态代理, 生成对应接口的实现类. 调用接口中的方法时, 执行动态代理的invoke方法
  2. ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
    方法, 获取接口中方法的信息(方法返回值类型/注解信息/参数类型/参数注解等)
  3. 创建OkHttpCall(封装Okttp中的Call为OkHttpCall)
  4. 执行CallAdapter#adapter(这里的CallAdapter实际为RxJavaCallAdapter), 在RxJavaCallAdapter#adapter中执行OkHttpCall#enqueue(以异步为例)执行网络请求, 并用Observable将结果发射出去成为Observable
上一篇下一篇

猜你喜欢

热点阅读