美文网首页
Retrofit源码解析

Retrofit源码解析

作者: dlihasa | 来源:发表于2019-02-01 19:03 被阅读16次
    • Retrofit在代码中的构建方式
    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http:/xx/xx/xx/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
    service = retrofit.create(APIService.class);
    service.getCall();
    
    • 根据构建方式,我们先来看一下Retrofit类源码

    (1)Retrofit中的七个重要的成员变量

    //Method是Http的请求方法,ServiceMethod是网络请求接口解析注解后的请求方法的对象
      private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
    //网络请求的工厂
      final okhttp3.Call.Factory callFactory;
    //网路请求的基地址,与接口中配置的地址拼接起来就是完整的请求地址
      final HttpUrl baseUrl;
    //数据转换器工厂的集合,工厂的作用用于生产数据转换器,比如converter-gson
      final List<Converter.Factory> converterFactories;
    //网络请求适配器的工厂集合,比如Call转换成RxJava平台的Call
      final List<CallAdapter.Factory> adapterFactories;
    //用于执行回调,处理异步请求。在Android平台默认使用的是MainThreadExcecutor主线程执行器
      final @Nullable Executor callbackExecutor;
    //布尔类型,是否需要立即解析接口中的方法,解析java接口中注解的请求方法和参数用到的
      final boolean validateEagerly;
    //构造方法
    Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
          List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
          @Nullable Executor callbackExecutor, boolean validateEagerly) {
        this.callFactory = callFactory;
        this.baseUrl = baseUrl;
        this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
        this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
        this.callbackExecutor = callbackExecutor;
        this.validateEagerly = validateEagerly;
      }
    

    (2)Retrofit中静态内部类Builder

    public static final class Builder {
        //基本上和Retrofit中成员变量一致
        private final Platform platform;
        private @Nullable okhttp3.Call.Factory callFactory;
        private HttpUrl baseUrl;
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
        private @Nullable Executor callbackExecutor;
        private boolean validateEagerly;
    
        Builder(Platform platform) {
          this.platform = platform;
          // Add the built-in converter factory first. This prevents overriding its behavior but also
          // ensures correct behavior when using converters that consume all types.
          converterFactories.add(new BuiltInConverters());
        }
    
        public Builder() {
          this(Platform.get());
        }
    
        Builder(Retrofit retrofit) {
          platform = Platform.get();
          callFactory = retrofit.callFactory;
          baseUrl = retrofit.baseUrl;
          converterFactories.addAll(retrofit.converterFactories);
          adapterFactories.addAll(retrofit.adapterFactories);
          // Remove the default, platform-aware call adapter added by build().
          adapterFactories.remove(adapterFactories.size() - 1);
          callbackExecutor = retrofit.callbackExecutor;
          validateEagerly = retrofit.validateEagerly;
        }
    
      (省略部分代码)
        ........
        ........
    
        /**
         * Create the {@link Retrofit} instance using the configured values.
         * <p>
         * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
         * OkHttpClient} will be created and used.
         */
        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<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
          adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    
          // Make a defensive copy of the converters.
          List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
    
          return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
              callbackExecutor, validateEagerly);
        }
      }
    

    成功建立一个Retrofit对象的标准:配置好Retrofit类里的成员变量,即配置好:
    serviceMethod:包含所有网络请求信息的对象
    baseUrl:网络请求的url地址
    callFactory:网络请求工厂
    adapterFactories:网络请求适配器工厂的集合
    converterFactories:数据转换器工厂的集合
    callbackExecutor:回调方法执行器

    在Retrofit内部类Builder默认的构造方法中,我们可以看到调用了带参数的构造方法this(Platform.get()),那么Platform是做什么的呢

    class Platform {
      private static final Platform PLATFORM = findPlatform();
    
      static Platform get() {
        return PLATFORM;
      }
    
      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();
      }
    
      @Nullable Executor defaultCallbackExecutor() {
        return null;
      }
    
      CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        if (callbackExecutor != null) {
          return new ExecutorCallAdapterFactory(callbackExecutor);
        }
        return DefaultCallAdapterFactory.INSTANCE;
      }
    
      boolean isDefaultMethod(Method method) {
        return false;
      }
    
      @Nullable Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
          @Nullable Object... args) throws Throwable {
        throw new UnsupportedOperationException();
      }
    
      @IgnoreJRERequirement // Only classloaded and used on Java 8.
      static class Java8 extends Platform {
        @Override boolean isDefaultMethod(Method method) {
          return method.isDefault();
        }
    
        @Override Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
            @Nullable Object... args) throws Throwable {
          // Because the service interface might not be public, we need to use a MethodHandle lookup
          // that ignores the visibility of the declaringClass.
          Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
          constructor.setAccessible(true);
          return constructor.newInstance(declaringClass, -1 /* trusted */)
              .unreflectSpecial(method, declaringClass)
              .bindTo(object)
              .invokeWithArguments(args);
        }
      }
    
      static class Android extends Platform {
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
          if (callbackExecutor == null) throw new AssertionError();
          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);
          }
        }
      }
    }
    
    • 其中findPlatform()方法中Class.forName("android.os.Build")

    Class.forName(xxx.xx.xx)返回的是一个类。
    Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段
    关于生成对象两种方式的区别可以看这里初始化一个类,生成一个实例的时候,newInstance()方法和new关键字

    • Android回调中的线程切换

    我们主要是看android,所以重点看其中静态内部类Android,该类中有一个defaultCallbackExecutor()的方法,返回的是Android中一个静态内部类MainThreadExecutor 的实例,我们可以看到在这里做了线程切换,采用Looper.getMainLooper()(主线程的looper)构造了handler,post了Runnable。

    (3)baseUrl说明

    public Builder baseUrl(String baseUrl) {
          checkNotNull(baseUrl, "baseUrl == null");
          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");
          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;
        }
    

    关于Retrofit中的baseUrl并没有强制怎么写,我可以写成https://api.github.com也可以写成 https://api.github.com/repos/,区别在哪呢?

    https://api.github.com的格式可以看成scheme://host[:port](此种类型是不是以 /(斜线) 结尾都可以,均不会抛出IllegalArgumentException异常);
    https://api.github.com/repos/的格式可以看成scheme://host[:port]/path(此种类型必须以/(斜线) 结尾,否则会抛出IllegalArgumentException异常).

    还是建议baseUrl统一以“/”结尾

    (4)GsonConverter/GsonConverterFactory

    addConverterFactory(Converter.Factory factory)就是将数据转换器工厂添加到Retrofit的数据转换器的集合中
    GsonConverterFactory.create(Gson gson)/GsonConverterFactory.create(),创建了一个持有gson实例的Gson数据转换器工厂,前者可以自己定义gson实例的一些特性,后者是采用了默认的gson实例。

    (5)CallAdapter/CallAdapterFactory

    addCallAdapterFactory(CallAdapter.Factory factory)同样就是将网络请求适配器工厂添加到Retrofit的网络请求适配器的集合中

    RxJava2CallAdapterFactory代码很短,以下是部分代码,其中Scheduler 是RxJava中的调度器,后面会介绍,通过create我们创建了一个RxJava2CallAdapterFactory,然后将其加到Retrofit的网络请求适配器的集合中

    /**
       * Returns an instance which creates synchronous observables that do not operate on any scheduler
       * by default.
       */
      public static RxJava2CallAdapterFactory create() {
        return new RxJava2CallAdapterFactory(null, false);
      }
    
      private final @Nullable Scheduler scheduler;
      private final boolean isAsync;
    
      private RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {
        this.scheduler = scheduler;
        this.isAsync = isAsync;
      }
    
    • 下面我们具体看一下RxJava2CallAdapterFactory
      RxJava2CallAdapterFactory继承自CallAdapter.Factory,Factory是接口CallAdapter的一个内部类,CallAdapter负责将Retroift中的Call转换成java对象,
    @POST("heart.do")
    Call<ABaseBean>  addFriendShip(@Body HashMap addInfo);
    @POST("heart.do")
    Observable<ABaseBean> addFriendShip(@Body HashMap addInfo);
    
    public interface CallAdapter<R, T> {
      
      Type responseType();
    
      T adapt(Call<R> call);
    
      abstract class Factory {
       
        public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
            Retrofit retrofit);
    
        protected static Type getParameterUpperBound(int index, ParameterizedType type) {
          return Utils.getParameterUpperBound(index, type);
        }
    
        protected static Class<?> getRawType(Type type) {
          return Utils.getRawType(type);
        }
      }
    }
    
    

    (1) Type responseType(),此处的Type就是Http请求返回的Response解析后的类型,并不是接口的返回类型,而是接口返回类型中泛型参数的实参,比如上述代码中ABaseBean。
    (2)T adapt(Call<R> call),T对应相应平台的对象,比如RxJava2CallAdapter中T对应Observable。
    (3)get方法根据接口类型、注解类型获取需要的CallAdapter
    (4)getRawType获取原始类型,在RxJava2CallAdapter中根据这个类型来选择生成不同的CallAdapter

    RxJava2CallAdapter中的adapt方法中,会将Retrofit.create()方法过程中生成的携带了ServiceMethod对象的OkHttpCall进行适配,后面会讲到:

    public Object adapt(Call<R> call) {
        Observable<Response<R>> responseObservable = isAsync
            ? new CallEnqueueObservable<>(call)
            : new CallExecuteObservable<>(call);
    
        Observable<?> observable;
        if (isResult) {
          observable = new ResultObservable<>(responseObservable);
        } else if (isBody) {
          observable = new BodyObservable<>(responseObservable);
        } else {
          observable = responseObservable;
        }
    
        if (scheduler != null) {
          observable = observable.subscribeOn(scheduler);
        }
    
        if (isFlowable) {
          return observable.toFlowable(BackpressureStrategy.LATEST);
        }
        if (isSingle) {
          return observable.singleOrError();
        }
        if (isMaybe) {
          return observable.singleElement();
        }
        if (isCompletable) {
          return observable.ignoreElements();
        }
        return observable;
      }
    

    上述判断条件分别是根据getRawType中获取到的类型生成的布尔值

    (6)retrofit.create(xxx.class),创建网络请求接口实例,create使用了外观模式和动态代理模式

    Retrofit中的create方法:

    public <T> T create(final Class<T> 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, @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);
                }
                ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.callAdapter.adapt(okHttpCall);
              }
            });
      }
    

    validateEagerly,这是上面提到过的Retrofit的七个重要的成员变量之一,是否提前验证解析接口,如果为true,调用eagerlyValidateMethods方法,这部分调用的说明写在下方代码注释中

    private void eagerlyValidateMethods(Class<?> service) {
        Platform platform = Platform.get();//获取平台,之前提到过Android、Java等
        for (Method method : service.getDeclaredMethods()) {//利用反射获取到网络请求接口中定义的method集合,遍历各个method
          if (!platform.isDefaultMethod(method)) {//此方法点进去可以看到默认返回false,则这里条件默认为true
            loadServiceMethod(method);
          }
        }
      }
    
    /**
    *该方法采用了常规的保存到缓存以及从缓存中获取目标对象的方式
    *获取的ServiceMethod是对应接口中网络请求的一个方法的封装,其中包含了url以及配置参数等等
    */
      ServiceMethod<?, ?> loadServiceMethod(Method method) {
      //serviceMethodCache,这是上面提到过的Retrofit的七个重要的成员变量之一,缓存生成的http请求接口方法的
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        if (result != null) return result;//如果从缓存中获取到,则直接返回
    
        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {//如果没有获取到,则创建并缓存到serviceMethodCache
            result = new ServiceMethod.Builder<>(this, method).build();
            serviceMethodCache.put(method, result);
          }
        }
        return result;//返回目标对象ServiceMethod
      }
    

    接下来,我们回到Retrofit的create方法中,非常重要的来了,动态代理动态创建网路请求,我们选其中重要的代码来看:

    ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
    return serviceMethod.callAdapter.adapt(okHttpCall);
    

    loadServiceMethod上面已经说过了,我们先来看看ServiceMethod这个类

    ServiceMethod的成员变量:

      //生产网络请求call的工厂
      final okhttp3.Call.Factory callFactory;
      //网络请求适配器,使网络请求适配不同平台,比如RxJava平台
      final CallAdapter<R, T> callAdapter;
       //网络请求基地址
      private final HttpUrl baseUrl;
      //数据转换器
      private final Converter<ResponseBody, R> responseConverter;
      //网络请求的方法,比如GET、POST等等
      private final String httpMethod;
      //网络请求的相对地址,与上面baseUrl拼接成完整的请求地址
      private final String relativeUrl;
      //网络请求的头部信息
      private final Headers headers;
     //网络请求的http报文的body类型
      private final MediaType contentType;
      private final boolean hasBody;
      private final boolean isFormEncoded;
      private final boolean isMultipart;
    //非常重要的:网络请求接口中参数、方法的处理器,包括注解啊、参数啊等等
      private final ParameterHandler<?>[] parameterHandlers;
    

    从loadServiceMethod方法中我们看到生成ServiceMethod时使用的也是构建者模式,看一下ServiceMethod的内部类Builder

    Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          this.methodAnnotations = method.getAnnotations();//网络请求接口中的请求方法以及header等注解,比如POST/GET/Multipart/FormUrlEncoded/Headers
          this.parameterTypes = method.getGenericParameterTypes();//网路请求接口方法中参数的类型
          this.parameterAnnotationsArray = method.getParameterAnnotations();//网路请求接口方法中注解的内容
        }
    
    public ServiceMethod build() {
          callAdapter = createCallAdapter();
          responseType = callAdapter.responseType();//获取该网络请求适配器的数据返回类型
    
          ...省略部分代码
    
          responseConverter = createResponseConverter();
          //遍历网络请求接口中方法的网络请求方式(就是接口名称上边那些)的注解
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);//其中通过if判断是否是哪种网络请求方式做相应解析
          }
    
         ...省略部分代码
    
          /**
          * 解析网络请求接口方法中的参数(注解和参数)
          */
          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);
        }
    
    

    生成ServiceMethod,主要是解析了网络请求接口中的注解和参数等,生成了相应的网络请求适配器和数据转换器。

    build中生成了ServiceMethod实例,我们分别来看看build方法中的关键步骤

      1. 生成网络请求的适配器 callAdapter = createCallAdapter();
    private CallAdapter<T, R> createCallAdapter() {
          Type returnType = method.getGenericReturnType();
          ...省略部分代码
          Annotation[] annotations = method.getAnnotations();
          try {
            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);
          }
        }
    

    最终调用了ServiceMethod创建时传进来的Retrofit对象的callAdapter(Type returnType, Annotation[] annotations)方法

    在retrofit中方法如下:

      public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
      }
      public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
          Annotation[] annotations) {
        ...省略部分代码
        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;
          }
        }
        ...省略部分代码
      }
    

    这里根据获取到的type和annotations从工厂类中生成相应的网络请求适配器,没有得到会抛出异常

      1. 生成数据转换器 responseConverter = createResponseConverter();
    private Converter<ResponseBody, T> createResponseConverter() {
          Annotation[] annotations = method.getAnnotations();
          try {
            return retrofit.responseBodyConverter(responseType, annotations);
          } catch (RuntimeException e) { // Wide exception range because factories are user code.
            throw methodError(e, "Unable to create converter for %s", responseType);
          }
        }
    

    同样,生成数据转换器也调用了ServiceMethod创建时传进来的Retrofit对象的方法,responseBodyConverter(Type type, Annotation[] annotations)

    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) {
        ...省略部分代码
        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;
          }
        }
        ...省略部分代码
      }
    

    converterFactories.get(i)获取到相应的数据转换器工厂,调用数据转换器工厂中相应的responseBodyConverter方法,比如常用的GsonConverterFactory

    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
          Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonResponseBodyConverter<>(gson, adapter);
      }
    
    • 3 之后build中还对网络请求接口中方法的注解和参数进行了解析,这部分都是在ServiceMethod类中的方法完成的,不再单独介绍,上述build方法代码中有简单的注释。

    到这部分,Retrofit.create()方法中的三行核心代码中的第一行,ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method),生成ServiceMethod的实现基本分析完毕。
    那么接下来继续看第二行OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args)

    final class OkHttpCall<T> implements Call<T> {
      private final ServiceMethod<T, ?> serviceMethod;//上面讲过的非常重要的一个对象
      private final @Nullable Object[] args;//参数
      private volatile boolean canceled;
      private @Nullable okhttp3.Call rawCall;//原生call,所有的操作最后实际上还是通过它来完成
      private @Nullable Throwable creationFailure; // Either a RuntimeException or IOException.
      private boolean executed;
    
       OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
        this.serviceMethod = serviceMethod;
        this.args = args;
      }
      ...省略了部分代码
    }
    

    OkHttpCall就是对OkHttp原生Call的封装,包含了各种Call的方法,比如enqueue、execute、cancel、isCanceled,总之需要用到OkHttp的Call中方法的来这里就对了。

    第二行代码简单分析之后,然后就是第三行代码了:return serviceMethod.callAdapter.adapt(okHttpCall)
    这里就是调用了adapt方法,比如加入使用了RxJava2CallAdapter,那callAdapter就对应RxJava2CallAdapter,如下:

    public Object adapt(Call<R> call) {
        Observable<Response<R>> responseObservable = isAsync
            ? new CallEnqueueObservable<>(call)
            : new CallExecuteObservable<>(call);
    
        Observable<?> observable;
        if (isResult) {
          observable = new ResultObservable<>(responseObservable);
        } else if (isBody) {
          observable = new BodyObservable<>(responseObservable);
        } else {
          observable = responseObservable;
        }
    
        if (scheduler != null) {
          observable = observable.subscribeOn(scheduler);
        }
    
        if (isFlowable) {
          return observable.toFlowable(BackpressureStrategy.LATEST);
        }
        if (isSingle) {
          return observable.singleOrError();
        }
        if (isMaybe) {
          return observable.singleElement();
        }
        if (isCompletable) {
          return observable.ignoreElements();
        }
        return observable;
      }
    

    (7)retrofit.create完成之后,具体去请求接口时:service.getCall(),因为service是一个接口,那接口去调用方法肯定是不行的,这里实际上是通过Retrofit中的create方法中动态代理进行了拦截,用InvocationHandler中的invoke方法进行实际操作,最后会返回一个OkHttpCall的适配器对象。

    (8)Retrofit的同步和异步请求:

    • Retrofit同步请求流程:

    ParameterHandler——>ServiceMethod——>Okhttp发送网络请求——>数据转换器converter

    同步请求依然得依靠OkHttpCall中封装的请求方法来执行:

    public Response<T> execute() throws IOException {
        okhttp3.Call call;
        ...省略部分代码
          call = rawCall;
          if (call == null) {
            try {
              call = rawCall = createRawCall();
            } catch (IOException | RuntimeException e) {
              creationFailure = e;
              throw e;
            }
          }
        }
        if (canceled) {//如果返回true,需要取消请求
          call.cancel();
        }
        return parseResponse(call.execute());
      }
    
      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;
      }
    

    上述代码我们发现会有一个生成原生call的过程,可以看到先调用了ServiceMethod的toRequest生成一个request对象,然后去执行request返回得到call,得到call的过程实际上是用OkHttp库生成的。

    ServiceMethod中的相关方法,根据传入的各个请求参数对应ParameterHandler进行解析:

    Request toRequest(@Nullable Object... args) throws IOException {
        RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
            contentType, hasBody, isFormEncoded, isMultipart);
    
        ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
    
        int argumentCount = args != null ? args.length : 0;
        ...省略部分代码
        for (int p = 0; p < argumentCount; p++) {
          handlers[p].apply(requestBuilder, args[p]);
        }
    
        return requestBuilder.build();
      }
    

    在execute方法中,最终用了原生的call去执行,执行的结果又调用了parseResponse(okhttp3.Response rawResponse)方法来解析

    Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();
        rawResponse = rawResponse.newBuilder()
            .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
            .build();
    
        int code = rawResponse.code();
        if (code < 200 || code >= 300) {
          try {
            // Buffer the entire body to avoid future I/O.
            ResponseBody bufferedBody = Utils.buffer(rawBody);
            return Response.error(bufferedBody, rawResponse);
          } finally {
            rawBody.close();
          }
        }
    
        if (code == 204 || code == 205) {
          rawBody.close();
          return Response.success(null, rawResponse);
        }
    
        ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
        try {
          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;
        }
      }
    

    可以看到获取网络请求的状态码等等,我们关注解析的核心过程serviceMethod.toResponse(catchingBody),又是调用了ServiceMethod中的方法

    R toResponse(ResponseBody body) throws IOException {
        return responseConverter.convert(body);
      }
    

    这里使用了数据转换器的convert方法,会使用我们的数据转换器,比如GsonRequestBodyConverter

    final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
      private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
      private static final Charset UTF_8 = Charset.forName("UTF-8");
    
      private final Gson gson;
      private final TypeAdapter<T> adapter;
    
      GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
      }
    
      @Override public RequestBody convert(T value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
      }
    }
    
    • Retrofit异步请求:
    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) {
              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<T> 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<T> response) {
            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              t.printStackTrace();
            }
          }
        });
      }
    

    异步请求会将执行结果交给一个回调执行器去处理请求结果。其中一些关键性的代码同步时已经说过,不再说了。


    【END】到这里,整个的网络请求就完成了,相应的源码也就分析完成了,Retrofit使用了的设计模式有构建者模式(Retrofit、ServiceMethod)、动态代理模式(实际调用请求方法时)、工厂模式(CallAdapter)、静态工厂模式(Platform)、外观模式/门面模式(Retrofit内部封装了很多子系统ServiceMethod、Factory等)、策略模式(CallAdapter是抽象层、具体的CallAdapter比如RxJava2CallAdapter)、适配器模式(CallAdapter)、观察者模式(OkHttpCall和Callback)
    外观模式/门面模式说明:比如android studio点击执行按钮去执行程序,内部实际上是执行了很多复杂的子系统之间的操作,开发者只需要通过android studio提供的按钮来操作就可以了,屏蔽了子系统之间的变化,高内聚低耦合。
    策略模式:比如要完成一项任务,有很多方法,可以根据不同的情况使用不同的方法来完成。
    工厂模式(强调生成不同的对象)和策略模式(adapt产生具体的实现,强调的是不同对象的方法不同的实现)
    观察者模式:一个被观察者可以对应多个观察者,多个观察者之间没有相互联系

    相关文章

      网友评论

          本文标题:Retrofit源码解析

          本文链接:https://www.haomeiwen.com/subject/ckxhjqtx.html