Retrofit2.0- 源码分析

作者: 负了时光不负卿 | 来源:发表于2017-12-13 19:34 被阅读67次

    1. 阅读引导

    在分析 Retrofit 源码之前,你首先得理解动态代理模式,因为Retrofit是通过动态代理的方式进行统一网络请求接口类的处理。Retrofit的代码量并不大,只是对OkHttp进行了封装,用更少的代码进行网络请求,明白动态代理模式之后,再看Retrofit网络请求处理流程就很清楚了。少量的代码使用大量的设计模式,所以Retrofit框架很值得我们去研究。

    2. Retrofit基本使用

    1. 配置Retrofit对象(与OkHttp相同,采用Builder模式)

    Retrofit retrofit = new Retrofit.Builder().baseUrl("xxxxx").build();

    1. 创建请求接口类
      public interface NetworkInterface {
        
        @GET("...")
        Call<MyResponse> listRepos(); //不同的方法代表不同的网络请求,可以声明请求方式(GET、POST..),请求头Header参数,请求体信息。
        
        ....
    }
    
    1. 创建接口类实例

    NetworkInterface networkInterface = retrofit.create(NetworkInterface.class);

    1. 调用方法,请求实际的网络请求
     Call<MyResponse> call = networkInterface.listRepos();
     call.enqueue(new Callback<MyResponse>() {  //与OkHttp不同,异步请求会回调到主线程
                @Override
                public void onResponse(Call<MyResponse> call, Response<MyResponse> response) { }
    
                @Override
                public void onFailure(Call<MyResponse> call, Throwable t) { }
            });
    

    3. Retrofit流程图

    Retrofit请求处理流程图.PNG

    说明: Retrofit只存在一个CallFactory,但是存在多个CallAdapterFactory和ConvertFactory,针对不同的请求接口方法,Retrofit会通过其返回值,选择特定的CallAdapterFactory和CovertFactory。

    4. Retrofit源码分析

    4.1 Retrofit创建过程

    通过前面基本的使用代码可以看出,Retrofit的创建也是采用Builder设计模式,通过new Retrofit.Builder().build()。我们先看看new Retrofit.Builder()的初始化工作。

    public static final class Builder {
      ... 
       public Builder() {
          this(Platform.get());
        }
    
       Builder(Platform platform) {
          converterFactories.add(new BuiltInConverters());
        }
      ...
    }
    

    通过Platform.get()获取当前平台对象Platform,然后调用它的另一个构造器,在这个构造器中,为ConvertFactory集合添加一个默认的ConvertFactory,不同的ConvertFactory产生的Convert对OkHttp网络请求返回的Response转化处理不一样,而默认ConvertFactory的Convert并没有对Response做太多处理,获得的数据依旧是Response对象。通过Builder.addConverterFactory(xxx)添加更多的ConvertFactory,比如xxx替换为GsonConverterFactory.create()添加GsonConvertFatory,它产生的GsonConvert就能将Response映射成JavaBean实体。

    回到主流程,还是看看Platform.get()是如何处理的吧!

    class Platform {
    
      private static final Platform PLATFORM = findPlatform();        //  静态工厂模式!
    
      static Platform get() {
        return PLATFORM;
      }
    
      private static Platform findPlatform() {     // 识别当前平台,如果是Android,就直接返回Android()对象实例
        try {
          Class.forName("android.os.Build");
          if (Build.VERSION.SDK_INT != 0) {
            return new Android();
          }
        } catch (ClassNotFoundException ignored) {
        }
         ...
       
        static class Android extends Platform {                    // Platform的子类,Android平台对象类
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {   // 获取Android平台的默认CallAdapterFactory对象
          if (callbackExecutor == null) throw new AssertionError();
          return new ExecutorCallAdapterFactory(callbackExecutor);
        }
    
        static class MainThreadExecutor implements Executor {       // 获取Android平台的默认线程执行调度器,其实就是通过Handler用于线程切换。
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
      }
      
      }
    

    总结: 通过new Retrofit.Builder()为ConvertFactory集合中添加一个默认ConvertFactory,创建一个包含默认的CallAdapterFactory、Executor的Android平台对象。注意,默认的ConvertFactory已经添加到了ConvertFactory集合中了,但是Android对象中的CallAdapterFactory并没有加入到CallAdapterFactory集合中。

    接着看new Retrofit.Builder().build()中的build()方法:

    public Retrofit build() {
          if (baseUrl == null) {                  // 强制需要通过.baseUrl("xxxxx")配置url
            throw new IllegalStateException("Base URL required.");  
          }
    
          okhttp3.Call.Factory callFactory = this.callFactory;
          if (callFactory == null) {
            callFactory = new OkHttpClient();    // 创建CallFactory用于生产Call对象,从这里也可以看出Retrofit最终还是通过OkHttp发送网络请求
          }
    
          Executor callbackExecutor = this.callbackExecutor;
          if (callbackExecutor == null) {
            callbackExecutor = platform.defaultCallbackExecutor();    // 获取Android平台对象中的默认Executor,里面通过Handler进行线程切换,上面有讲过!
          }
    
          List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
    
             // 此处将Android平台对象中的CallAdapterFactory添加到Retrofit的CallAdapterFactory集合中.
             // 注意同时将Executor也传入到这个CallAdapterFactory中,那么工厂生产出来的CallAdapter就也就具有线程切换的能力。
           adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); 
    
          List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
    
          return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
              callbackExecutor, validateEagerly);                  // 通过Builder创建Retrofit,并将配置参数作为参数传入
        }
    

    再看看一下Retrofit的构造:

      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;
      }
    
    4.2 核心动态代理代码

    NetworkInterface networkInterface = retrofit.create(NetworkInterface.class);

    public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service);              //  1.   判断网络请求接口类的合法性
    
        if (validateEagerly) {                                  //   2.   是否需要提前对 网络请求接口类 中的方法进行提前处理,即为接口中的每一个方法提前处理成 SeviceMethod(核心类)对象,并缓存。
          eagerlyValidateMethods(service);
        }
                                                   //   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 {
                  ... 
                                                     // 4. 将接口中的方法处理成serviceMethod。
                 ServiceMethod<Object, Object> serviceMethod =  (ServiceMethod<Object, Object>) loadServiceMethod(method); 
                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);  // 5. 创建 OkHttpCall对象,传入serviceMethod对象和调用方法实际参数。 
                return serviceMethod.callAdapter.adapt(okHttpCall);  // 6. 将Call对象进行CallAdapter进行转化( 比如RxCallAdapter将Call转化为Observable ) 注意Call还没有被执行,即没有进行网络请求。
              }
            });
      }
    

    总结:
    (一 ) retrofit.create(xx)方法中处理分三步:

      1. 判断网络请求接口类的合法性
      1. 是否需要提前对 网络请求接口类 中的方法进行预处理
      1. 返回生成动态代理类

    (二) 调用网络请求接口方法,动态代理类中的invoke()方法被执行,也处理也分三步:

      1. 将对应的执行方法转化成ServiceMethod对象
      1. 创建OkHttpCall对象
    • 3 OkHttpCall通过CallAdapter进行Call的转化
    4.3 调用接口方法

    Call<MyResponse> call = networkInterface.listRepos();

    在通过上面的说明,当调用网络请求接口类方法时,就会调用invoke方法,传入通过反射获取Method和执行方法参数args,因为没有调用call.execute()或call.enqueue(Callback),所以Call并没有执行。接下来我们具体看看invoke方法体中三部曲吧!

      1. 将对应的执行方法转化成ServiceMethod对象
      ServiceMethod<?, ?> loadServiceMethod(Method method) {
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);  // 先从缓存中取,如果在之前分析的create()中validateEagerly = true 必然从缓存中能取到。
        if (result != null) return result;
    
        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {
            result = new ServiceMethod.Builder<>(this, method).build();  // 根据Method创建ServiceMethod对象
            serviceMethodCache.put(method, result);        // 将创建的ServiceMethod进行缓存
          }
        }
        return result;
      }
    

    接下来看看,ServiceMethod的创建!

    ServiceMethodBuilder.class

     Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;                         // 1. 将外观类 Retrofit传入
          this.method = method;                       
          this.methodAnnotations = method.getAnnotations();  //  2. 获取方法上的注解(@GET @POST... )
          this.parameterTypes = method.getGenericParameterTypes();   
          this.parameterAnnotationsArray = method.getParameterAnnotations();  // 3. 获取参数注解(@Query ...)
        }
    
    public ServiceMethod build() {
          callAdapter = createCallAdapter();               // 4. 获取该方法对应的CallAdapter
          responseType = callAdapter.responseType();  //  5. 获取该方法的响应类型,比如Response或者自定义的JavaBean
          ... 
          responseConverter = createResponseConverter();   // 6. 根据上面获取的响应类型获取对应的Convert
    
          for (Annotation annotation : methodAnnotations) {  // 7. 解析第二步得到的方法注解
            parseMethodAnnotation(annotation);
          }
          ... 
          int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler<?>[parameterCount];
          for (int p = 0; p < parameterCount; p++) {
            Type parameterType = parameterTypes[p];
             ... 
            Annotation[] parameterAnnotations = parameterAnnotationsArray[p];   // 8. 解析第三步得到的参数注解
             ... 
            parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
          }
    
          return new ServiceMethod<>(this);  //  创建ServiceMethod对象
        }
    
    

    之前有说过Retrofit中可以有多个ConvertFactory和CallAdapterFactory,通过上面的第4步和第6步获取该Method对应的ConvertFactory和CallAdapterFactory。这两种Factory的适配过程近乎一样,所以这里只做CallAdapterFactory的配对过程。

    private CallAdapter<T, R> createCallAdapter() {
          Type returnType = method.getGenericReturnType();
          ... 
          Annotation[] annotations = method.getAnnotations();
          ...
          return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
        }
    

    Retrofit.class

    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
                                                                    // type: return 返回的类型,比如Call、Observable
         ...
        int start = adapterFactories.indexOf(skipPast) + 1;      // 用于做CallAdapterFactory跳过处理,默认start = 0
        for (int i = start, count = adapterFactories.size(); i < count; i++) {
          CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
          if (adapter != null) {
            return adapter;
          }
        }
        ...
    }
    

    每一个CallAdapterFactory需要实现一个get(returnType,xxx)方法,如果能处理这个returnType就返回对应的CallAdapter对象。比如默认returnType为Call,那么就被默认的CallAdapterFactory接受处理,这个CallAdapterFactory在Android平台类中defaultCallAdapterFactory()获得(4.1 Retrofit创建过程 有说明)

    Android.class

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
          if (callbackExecutor == null) throw new AssertionError();
          return new ExecutorCallAdapterFactory(callbackExecutor);
        }
    

    ExecutorCallAdapterFactory.class

    final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
      final Executor callbackExecutor;
    
      ExecutorCallAdapterFactory(Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
      }
    
      @Override
      public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
          return null;
        }
        final Type responseType = Utils.getCallResponseType(returnType);
        return new CallAdapter<Object, Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }
    
          @Override public Call<Object> adapt(Call<Object> call) {
            return new ExecutorCallbackCall<>(callbackExecutor, call);
          }
        };
      }
    

    总结: ServiceMethod通过Builder模式创建,包含了Retrofit对象,对执行的Method进行剖析,像方法注解、参数注解、参数类型、CallAdapter、ConvertAdapter,所以一个ServiceMethod对象包含了网络请求需要的所有信息。

      1. 创建OkHttpCall对象

    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

    OkHttpCall.class

     OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
        this.serviceMethod = serviceMethod;
        this.args = args;
      }
    
    • 3 OkHttpCall通过CallAdapter进行Call的转化

    serviceMethod.callAdapter.adapt(okHttpCall);

    如果接口方法返回类型是Call的话,CallAdapter就是默认的CallAdaterFactory创建的CallAdapter,即ExecutorCallAdapterFactory类中get()方法返回的CallAdapter:

    new CallAdapter<Object, Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }
    
          @Override public Call<Object> adapt(Call<Object> call) {
            return new ExecutorCallbackCall<>(callbackExecutor, call);
          }
        };
    
    

    接着定位返回的CallAdapter中adapt()方法,最后返回了一个new ExecutorCallbackCall<>(callbackExecutor, call); 对象,代表serviceMethod.callAdapter.adapt(okHttpCall);的执行结束,并向外暴露一个ExecutorCallbackCall对象。

      1. 同步异步网络请求
    // 同步请求
    call.execute();
    // 异步请求
    call.enqueue(new Callback<MyResponse>() {  //与OkHttp不同,异步请求会回调到主线程
                @Override
                public void onResponse(Call<MyResponse> call, Response<MyResponse> response) { }
    
                @Override
                public void onFailure(Call<MyResponse> call, Throwable t) { }
            });
    

    与同步相比,异步相对来说复杂一点点,这里只分析异步,相信异步看懂了,同步肯定不在话下。

    ExecutorCallbackCall.class

    @Override public void enqueue(final Callback<T> callback) {
          ... 
          delegate.enqueue(new Callback<T>() {                 // delegate是由serviceMethod.callAdapter.adapt(okHttpCall); 传入的,所以最终的网络请求还是通过OkHttpCall进行。
            @Override public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(new Runnable() {       // callbackExecutor 是Android平台对象类中的MainThreadExecutor 主要将线程切换到主线程
                @Override public void run() {
                  if (delegate.isCanceled()) {
                     ...
                  } else {
                    callback.onResponse(ExecutorCallbackCall.this, response);
                  }
                }
              });
            }
    
            @Override public void onFailure(Call<T> call, final Throwable t) {
              callbackExecutor.execute(new Runnable() {
                @Override public void run() {
                  callback.onFailure(ExecutorCallbackCall.this, t);
                }
              });
            }
          });
        }
    

    OkHttpCall.class

    @Override public void enqueue(final Callback<T> callback) {
       ...
       call.enqueue(new okhttp3.Callback() {                    // 这个Call才是OKHttp中正宗的Call
          @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);
          }
       ... 
    }
    

    5. Retrofit设计模式

    • Builder模式
    • 外观模式
    • 静态工厂模式
    • 动态工厂模式
    • 适配器模式
    • 动态代理模式

    相关文章

      网友评论

        本文标题:Retrofit2.0- 源码分析

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