Retrofit源码解析

设计模式:建造者模式、工厂方法模式、外观模式、代理模式、单例模式、策略模式、装饰模式、适配器模式、代理模式

一、Retrofit网络请求步骤

  • 通过解析网络请求接口的注解 配置 网络请求参数
  • 通过动态代理 生成 网络请求对象
  • 通过网络请求适配器 将 网络请求对象 进行平台适配
  • 通过网络请求执行器 发送网络请求
  • 通过数据转换器 解析服务器返回的数据
  • 通过回调执行器 切换线程
  • 用户在主线程处理返回结果
  • Call网络请求执行器
    作用:创建HTTP网络请求
  • CallAdpater网络请求适配器
    作用:网络请求执行器的适配器,将默认的网络请求执行器转换成适合被不同平台调用的网络请求执行器
  • Converter数据转换器
    作用:将返回数据解析成我们需要的数据类型
  • CallBackExecutor回调执行器
    作用:线程切换(子线程 -->主线程)

二、源码解析

(1)创建Retrofit实例

    private static Retrofit provideRetrofit() {
        File cacheFile = new File(CPApplication.getContext().getCacheDir(), "cache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
        OkHttpClient client = new OkHttpClient.Builder()
                .cache(cache) //设置缓存
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .addNetworkInterceptor(getRequestHeader())
                .addInterceptor(getHttpLoggingInterceptor())
                .addInterceptor(getResponseHeader())
                .addInterceptor(getCacheInterceptor())
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(NetworkInterface.HOST)//设置网络请求的Url地址
                .addConverterFactory(GsonConverterFactory.create())//设置数据解析器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//支持RxJava平台
                .client(client)
                .build();
        return retrofit;
    }

(2)Retrofit类源码

public final class Retrofit {
    //网络请求配置对象
    private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
    //网络请求工厂:生产网络请求器
    final okhttp3.Call.Factory callFactory;
    //网络请求的url地址
    final HttpUrl baseUrl;
    //网络请求适配器工厂的集合:放置网络请求适配器工厂
    final List<Converter.Factory> converterFactories;
    //数据转换器工厂的集合:放置数据转换器工厂
    final List<CallAdapter.Factory> callAdapterFactories;
    //回调方法执行器
    final @Nullable Executor callbackExecutor;
    //是否提前对业务接口中的注解进行验证转换的标志位
    final boolean 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;
    }
    //code...
}

成功建立一个Retrofit对象的标准:配置好Retrofit类里的成员变量

  • serviceMethod:包含所有网络请求信息的对象
  • baseUrl:网络请求的url地址
  • callFactory:网络请求工厂
  • adapterFactories:网络请求适配器工厂的集合
  • converterFactories:数据转换器工厂的集合
  • callbackExecutor:回调方法执行器
    (3)Builder类源码
  public static final class Builder {
    //Builder类的成员变量与Retrofit类的成员变量是对应的。所以Retrofit类的成员变量基本上是通过Builder类进行配置
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
      this.platform = platform;
    }

    //Builder的构造方法
    public Builder() {
      //用this调用自己的有参构造方法Builder(Platform platform)
      this(Platform.get());
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;
      // Do not add the default BuiltIntConverters and platform-aware converters added by build().
      for (int i = 1,
          size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
          i < size; i++) {
        converterFactories.add(retrofit.converterFactories.get(i));
      }
      // Do not add the default, platform-aware call adapters added by build().
      for (int i = 0,
          size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();
          i < size; i++) {
        callAdapterFactories.add(retrofit.callAdapterFactories.get(i));
      }
      callbackExecutor = retrofit.callbackExecutor;
      validateEagerly = retrofit.validateEagerly;
    }

    //设置网络请求执行器
    public Builder client(OkHttpClient client) {
      return callFactory(Objects.requireNonNull(client, "client == null"));
    }

    //使用okhttp进行网络请求
    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = Objects.requireNonNull(factory, "factory == null");
      return this;
    }

    //用于配置Retrofit类的网络请求url地址
    public Builder baseUrl(String baseUrl) {
      //把String类型的url参数转化为适合OKhttp的HttpUrl类型
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      //最终返回带httpUrl类型参数的baseUrl()
      return baseUrl(HttpUrl.get(baseUrl));
    }

    public Builder baseUrl(HttpUrl baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      //把URL参数分割成几个路径碎片
      List<String> pathSegments = baseUrl.pathSegments();
      //检测最后一个碎片来检查URL参数是不是以"/"结尾
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

    //创建GsonConverterFactory放入到 converterFactories数组设置数据解析器
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }

    //创建RxJava2CallAdapterFactory放入到 callAdapterFactories数组支持RxJava平台
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }

    //回调执行器
    public Builder callbackExecutor(Executor executor) {
      this.callbackExecutor = Objects.requireNonNull(executor, "executor == null");
      return this;
    }

    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      //配置网络请求执行器
      okhttp3.Call.Factory callFactory = this.callFactory;
      //如果没指定,则默认使用OkHttpClient
      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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      //配置数据转换器工厂
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

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

      //最终返回一个Retrofit的对象,并传入上述已经配置好的成员变量
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
}

Platform源码

class Platform {
  //将findPlatform()赋给静态变量
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      //要求JVM查找并加载指定的类
      Class.forName("android.os.Build");
      //如果是Android平台,就创建并返回一个Android对象并返回
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform(true);
  }
  //code...
}

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 {
      //获取与Android主线程绑定的Handler 
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override 
      public void execute(Runnable r) {
        //在UI线程进行对网络请求返回数据处理等操作
        handler.post(r);
      }
    }
  }

GsonConverterFactory.creat()源码

public final class GsonConverterFactory extends Converter.Factory {
  
  public static GsonConverterFactory create() {
    //创建一个Gson对象
    return create(new Gson());
  }

  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    //创建了一个含有Gson对象实例的GsonConverterFactory
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }
  //code...
}

通过查看源码GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory,并返回给addConverterFactory()
通过addConverterFactory方法将上面创建的GsonConverterFactory放入到converterFactories数组
(4)创建网络请求接口

retrofit.create(NetworkInterface.class).registerLogin("");

create源码

  public <T> T create(final Class<T> 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 {
            // 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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

  //一个 ServiceMethod 对象对应于网络请求接口里的一个方法
  ServiceMethod<?> loadServiceMethod(Method method) {
    //首先会尝试根据方法从缓存中取出 ServiceMethod 实例
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;
   
    synchronized (serviceMethodCache) {
       //如果没有,在锁保护之后还会再尝试一次
      result = serviceMethodCache.get(method);
      if (result == null) {
        //还是没有的情况下,创建 ServiceMethod,最后放到 serviceMethodCache 缓存里
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

ServiceMethod的创建过程
查看ServiceMethod.parseAnnotations方法源码

  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    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);
  }

查看RequestFactory.parseAnnotations & Builder源码

  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
  
  //code..

  //控制ServiceMethod对象的生成流程
  static final class Builder {

     //code..

    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() {
      //解析网络请求接口中方法的注解。主要是解析获取Http请求的方法
      for (Annotation annotation : methodAnnotations) {
        //处理主要是调用此方法
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(method,
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      //获取当前方法的参数数量
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      //parameterAnnotationsArray为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        //该对象的创建过程就是对方法参数中注解进行解析
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError(method, "Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError(method, "Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError(method, "Multipart method must contain at least one @Part.");
      }

      return new RequestFactory(this);
    }
    
    //code...

  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容