Retrofit 源码解析

1.背景

Retrofit 是一个基于okHttp为基础的网络请求框架,底层用到了okHttp来进行网络请求,并且结合RXJava能做到非常强大的切换控制作用是现在主流的Android开发框架,并且Retrofit在设计之中用到了大量的设计模式,其实非常适合我们去学习。

2.基础使用

我们可以看到它的基本使用 其实就是用建造者模式建造了一个Retrofit对象 然后创建了一个call对象 ,调用call对象的一个enqueue传入回调接口,在不同的接口中获取不同的回调
 Retrofit build = new Retrofit.Builder().baseUrl("wwww.huya.com")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        IpService ipService = build.create(IpService.class);
        Call<IpData> call = ipService.getIpData();
        call.enqueue(new Callback<IpData>() {
            @Override
            public void onResponse(Call<IpData> call, Response<IpData> response) {

            }

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

            }
        });

3.源码分析

我们先来看一下Builder这个内部类 具体每个变量已经有解释了,调用了Builder构造函数我们来看一下Platform.get()方法做了什么
  private final Platform platform; //平台
    private @Nullable okhttp3.Call.Factory callFactory; //call工厂
    private HttpUrl baseUrl;//基础url
    private final List<Converter.Factory> converterFactories = new ArrayList<>();//转换器工厂
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();//适配器工厂
    private @Nullable Executor callbackExecutor; //回调执行器
    private boolean validateEagerly;
  public Builder() {
      this(Platform.get());
    }
我们看到其实调用了findPlatform()方法我们跟进去看一下
private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }
  }
其实是根据不同平台调用 我们肯定是Android对象啦 点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) {
    }
    return new Platform();
  }
其实是做了一些初始化操作
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);
      }
    }
  }
然后我们回到基础使用代码的baseUrl其实就是组装了url然后今晚判断是否合法
 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;
    }
我们看到addConverterFactory其实是将转换工厂加入到了集合
  public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
我们看到addCallAdapterFactory其实也是加入到了集合
 public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
我们可以看到最终调用build()方法生成一个retrofit对象
 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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

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

      // 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());
      converterFactories.addAll(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
这个retrofit里面已经有了 baseUrl 是一个队url的封装对象包含很多东西不需要太纠结 callFactory 这个其实是OkHttpClient 其实是准备调用okHttp的封装好的一个类,converterFactories这个是转换工厂默认是json类型就是我们上面加入的一个那个json转换工厂具体Gson如何转换我们先不用关心callAdapterFactories 这个是数据适配工厂,一般如果我们再上面加入了RXJava的call适配工厂 这个就会被加入进去callbackExecutor 这个是回调的执行 validateEagerly是否提前判断 其实只是我们没有设置也有提供给我们设置的方法
 Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> 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;
  }
最后一个 Retrofit就被我们建造好了
我们接下来看 Retrofit调用的create方法 传入了接口类做了什么
 IpService ipService = build.create(IpService.class);
我们可以看到 它先调用了 eagerlyValidateMethods方法然后用了一个代理模式返回了这个对象 我们先看eagerlyValidateMethods这个方法做了啥子
 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.adapt(okHttpCall);
          }
        });
  }
 private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
 private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
这个方法其实是将接口里面的方法遍历然后每个方法创建自己的ServiceMethod 当然 它也做了缓存操作 如果有就不用创建了 没有的话就创建一个新的ServiceMethod方法 那么ServiceMethod它到底是什么,其实它是一个将接口中的方法进行解析的一个类能 将注解进行解析,持有retrofit对象,将要请求的东西全部搞好放在ServiceMethod这个类中跑包括头 方法 注解 解析器 等
回到create方法 我们可以看到在代理模式中调用了这样的代码
   ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
拿到了一个ServiceMethod方法 然后创建了一个OkHttpCall,这个OkHttpCall是发起okHttp请求的一个call 然后调用serviceMethod.adapt(okHttpCall); 其实就是把结果构建成上面传入的适配工厂类,我们看一下 如果传入RxJava2CallAdapter的话会做什么操作
 @Override 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;
  }
其实就是将结果搞成一个observable 这个是支持RxJava的一个对象我们可以将上面的基本使用改成这样子
        Observable<IpData> observable = ipService.getIpData();
这样就可以很好接入RXJava这套框架体系了
我们接下来看enqueue 如果不考虑RXJAVA的话 结果就是调用下面代码
 @Override 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) {
          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<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();
        }
      }
    });
  }

其实就是调用serviceMethod的tocall方法组装成一个真正的call请求然后调用OKHTTP的真正请求方法,将真正的网络请求交给OkHttp,返回结果调用parseResponse 方法解析返回的数据,这个就是整个的执行流程
 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();
        }
      }
    });

4.Retrofit设计模式总结

(1)建造者设计模式
建造者模式在这个框架可以说是随处可见,基本套路就是在Retrofit内部有一个Build 内部类,将要设置的数据全部用过build的方式设置进去,然后返回这个对象,这样就可以一直链式调用,最后通过build方法,将最后的数据new给Retrofit这个对象 这个对象就算是建造完成
(2)外观设计模式
外观设计模式就是让开发者感觉不到其他子系统的存在,比如Retrofit中,有很多子系统 像Call 缓存 等等子系统,但是它不需要让用户知道这些东西,子系统的运行都在Retrofit中可以控制好
(3)代理模式
代理模式就是通过代理的方式去执行方法,分为静态代理和动态代理,动态代码就是像这样 动态执行这个类下面的所有方法
 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 {
            return serviceMethod.adapt(okHttpCall);
          }
        });
(4)适配器模式
适配器模式就是可以适配多种数据来源或者数据可能,比如在一开始加入RxJava的适配器,那么我们就可以支持RXJava的操作方式,加入其它平台的就可以适配其它平台的方式
(5)工厂模式
工厂模式就是可以生产多种call根据方法的不同,生产出不同的Call对象

5.总结

通过上面的分析我们要知道的一点就是Retrofit说简单其实是比较简单的,它就是对一个请求进行封装,运用了大量的设计模式,让请求可以更加有扩展性,且可以接入RXJava等,但是它其实是对请求做了处理和封装,真正的请求是交给了OKHttp进行处理,它是做了请求前的前期工作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值