美文网首页
Retrofit2源码解析

Retrofit2源码解析

作者: 阿泽Leo | 来源:发表于2019-05-10 16:00 被阅读0次

    本篇文章基于 retrofit2 的 2.5.0 版本。


    首先我们想要分析源码,那就首先要会使用。看下简单用法:

    public interface GitHubService {
        @GET("users/{user}/repos")
        Call<List<Repo>> listRepos(@Path("user") String user);
    }
    
    //创建Retrofit对象
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .build();
    //创建service
    GitHubService service = retrofit.create(GitHubService.class);
    //创建Call
    Call<List<Repo>> repos = service.listRepos("octocat");
    //开始请求
    repos.enqueue(new Callback<List<Repo>>() {
        @Override
        public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
    
        }
        @Override
        public void onFailure(Call<List<Repo>> call, Throwable t) {
    
        }
    });
    

    1.

    从create方法入手,发现是动态代理。
    调用Platform.get获取platform,暂时不知道是干嘛的,
    接着看核心方法是loadServiceMethod(method).invoke(..);

    image.png

    2.

    进入loadServiceMethod方法中,找到核心方法parseAnnotations()。从方法名上看出是解析注解的意思。

    image.png

    3.

    进入parseAnnotations方法中,有两处核心代码。

    RequestFactory.parseAnnotations(retrofit, method);

    HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);

    image.png

    4.

    先查看第一处核心代码RequestFactory.parseAnnotations(retrofit, method);
    发现是使用了Builder模式创建了RequestFactory对象,看里面的方法,发现有一个create方法可以使用,进入方法里面。

    image.png image.png
    • 先看第一段代码RequestBuilder,查看类里面的方法,字面意思是quest的构造器。
      image.png
    • 再看第二段代码,用刚才的RequestBuilder对象创建了一个okhttp3.Request对象。查看里面的方法。知道大概是一个真正用来发起请求的类。先记着,还没有用到。
      image.png

    5.

    现在回到第3个步骤继续。查看第二处核心代码HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);

    image.png

    看注释可以了解到,ServiceMethod最好缓存起来使用,这样就能解释上面第2个步骤的缓存了。接着往下看核心代码:
    ①创建了CallAdapter。

    追踪方法得知最终是由Retrofit对象的nextCallAdapter方法获取,内部是从callAdapterFactories这个List中取出,由于还没有查看Retrofit类的实现,暂时先放着。

    ②创建了ResponseConverter

    追踪方法最终还是由Retrofit对象的nextResponseBodyConverter方法获取,与上一个类似,从converterFactories中取出,还是先放着。

    ③获取callFactory

    这个更直接,从retrofit中取出成员变量callFactory。

    ④传入4个参数,创建一个HttpServiceMethod对象

    最后看看HttpServiceMethod的构造方法,发现只是设置了变量。

    6.

    回到最初开始分析时的代码loadServiceMethod(method).invoke(..);
    loadServiceMethod(method)实际上返回了HttpServiceMethod对象,查看里面的invoke方法。

    image.png
    其中4个变量都是构造方法传进来的,继续查看callAdapter.adapt方法。发现是一个接口方法。
    T adapt(Call<R> call);
    

    现在需要找到CallAdapter实现类。从上一步骤知道,这里的4个成员变量callAdapter,requestFactory,callFactory,responseConverter中除了requestFactory是刚才知道怎么创建的,其他都是从Retrofit对象中取出来的。

    7.

    现在需要知道Retrofit对象是怎么构建的,回到最初的简单用法中得知,Retrofit是从Retrofit.Builderbuild方法创建的。

    //创建Retrofit对象
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .build();
    

    8.

    现在从build方法入手。

    /**
     * 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> 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());
    
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
    

    先看注释,明白这里就是通过一些配置来创建一个Retrofit对象,即Builder模式。
    看到callFactory的创建,默认是一个OkHttpClient对象,这一点注释也有说明。
    创建了一个Executor,使用了platform的defaultCallbackExecutor方法。
    创建了一个callAdapterFactories的List,把默认的CallAdapterFactories添加进去,还是使用了platform的方法,defaultCallAdapterFactories(callbackExecutor)。
    类似的实现方式,创建了converterFactories,也是添加了默认的对象。
    最后创建了一个Retrofit对象并返回,把参数设置到了对象中。

    现在清楚了第6步骤使用的对象都是在Retrofit创建时就已经配置好了,但是我们继续查看时,发现它们都是接口,所以我们需要找出它们的实际对象,即是要找出它们实例化的代码。

    9.

    由于默认的Executor,CallAdapter,ConverterFactories都是由Platform的defaultXXXX方法创建的,所以分析一下platform这个对象其实是什么。回到第一步骤,Retrofit的create方法的return中的一行代码。

    private final Platform platform = Platform.get();
    

    进去看看

    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();//这里看到Platform对象其实就是Android对象
        }
      } catch (ClassNotFoundException ignored) {
      }
      try {
        Class.forName("java.util.Optional");
        return new Java8();
      } catch (ClassNotFoundException ignored) {
      }
      return new Platform();
    }
    

    现在知道了platform其实就是Android对象,我们查看Retrofit的build方法里的platform的调用:

    • callbackExecutor = platform.defaultCallbackExecutor();
    • platform.defaultCallAdapterFactories(callbackExecutor)
    • platform.defaultConverterFactoriesSize()
    • platform.defaultConverterFactories()
    static class Android extends Platform {
      @IgnoreJRERequirement // Guarded by API check.
      @Override boolean isDefaultMethod(Method method) {
        if (Build.VERSION.SDK_INT < 24) {
          return false;
        }
        return method.isDefault();
      }
    
      //①默认的Executor是MainThreadExecutor
      @Override public Executor defaultCallbackExecutor() {
        return new MainThreadExecutor();
      }
    
      //②默认的CallAdapterFactories
      @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
          @Nullable Executor callbackExecutor) {
        if (callbackExecutor == null) throw new AssertionError();
        //CallAdapterFactory的默认对象,传入了callbackExecutor
        ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
        return Build.VERSION.SDK_INT >= 24
          ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
          : singletonList(executorFactory);
      }
    
      //默认的CallAdapterFactoriesSize
      @Override int defaultCallAdapterFactoriesSize() {
        return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
      }
    
      //④默认的ConverterFactories
      @Override List<? extends Converter.Factory> defaultConverterFactories() {
        return Build.VERSION.SDK_INT >= 24
            ? singletonList(OptionalConverterFactory.INSTANCE)
            : Collections.<Converter.Factory>emptyList();
      }
    
      //③默认的ConverterFactoriesSize
      @Override int defaultConverterFactoriesSize() {
        return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
      }
    
      //默认的Executor中的execute方法就是用handler发消息,把操作放到主线程中
      static class MainThreadExecutor implements Executor {
        private final Handler handler = new Handler(Looper.getMainLooper());
    
        @Override public void execute(Runnable r) {
          handler.post(r);
        }
      }
    }
    

    10.

    现在回看第5个步骤,发现了使用的参数都是由这里的对象中取出的,那么可以继续分析第6步骤的方法:


    image.png

    callAdapter的获取,在nextCallAdapter方法中
    核心callAdapterFactories.get(i).get(returnType, annotations, this);

    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
        Annotation[] annotations) {
      ...
    
      int start = callAdapterFactories.indexOf(skipPast) + 1;
      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的默认实现就是ExecutorCallAdapterFactory,进入该类查看get方法。

    @Override public @Nullable CallAdapter<?, ?> get(
        Type returnType, Annotation[] annotations, Retrofit retrofit) {
      ...
      //创建了一个CallAdapter
      return new CallAdapter<Object, Call<?>>() {
        @Override public Type responseType() {
          return responseType;
        }
    
        //核心方法
        @Override public Call<Object> adapt(Call<Object> call) {
          return new ExecutorCallbackCall<>(callbackExecutor, call);
        }
      }; 
    }
    

    到这里其实就是callAdapter的实现了。

    11.

    继续查看adapt方法,前文得知传入的call就是new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
    查看内部类ExecutorCallbackCall:

    image.png

    我们使用时就是调用了Call的enqueue方法,这里看到enqueue方法的真正实现。
    其中delegate是刚才传入的OkHttpCall对象,callbackExecutor我们知道其实是MainThreadExecutor对象,所以这里的enqueue方法中主要做了两件事:

    • 调用OkHttpCall的enqueue发起请求
    • 调用MainThreadExecutor的execute方法,内部其实就是用主线程的Handler切换到主线程去运行。

    我们继续查看OkHttpCall的enqueue方法:

    @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 {
            //创建okhttp3.Call对象
            call = rawCall = createRawCall();
          } catch (Throwable t) {
            throwIfFatal(t);
            failure = creationFailure = t;
          }
        }
      }
    
      if (failure != null) {
        callback.onFailure(this, failure);
        return;
      }
    
      if (canceled) {
        call.cancel();
      }
      //调用了okhttp3.Call对象的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) {
            throwIfFatal(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();
          }
        }
      });
    }
    

    发现很长,其实里面的主要工作就是:

    • 创建okhttp3.Call的对象
    • 调用这个对象的enqueue方法

    我们来看一下这个okhttp3.Call对象是什么,查看createRawCall()方法:

    private okhttp3.Call createRawCall() throws IOException {
      //这个callFactory其实就是okhttpClient
      okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
      if (call == null) {
        throw new NullPointerException("Call.Factory returned null.");
      }
      return call;
    }
    

    由上文得知这里的callFactory就是Retrofit.build()中创建的OkhttpClient对象。
    这里的newCall方法就是创建一个OkHttp的Call了,所以说Retrofit是基于OkHttp来实现的。

    @Override public Call newCall(Request request) {
      return RealCall.newRealCall(this, request, false /* for web socket */);
    }
    

    总结

    1. 调用Retrofit.Builder的build方法,初始化必要的参数。
      有baseUrl、callFactory、callbackExecutor、callAdapterFactories、converterFactories等。
    2. 调用retrofit的create方法,包装出一个自定义的接口GitHubService的Class。
      内部实现是动态代理,具体实现是HttpServiceMethod的对象。其中包含了对接口方法注解的解析。
    3. 最后调用enqueue发起请求内部使用了okhttp。

    谢谢大家能看到末尾,如果发现有错误的地方或者有疑问的地方请各位留言,谢谢!

    相关文章

      网友评论

          本文标题:Retrofit2源码解析

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