美文网首页
retrofit 源码分析

retrofit 源码分析

作者: 虫二无边 | 来源:发表于2016-12-15 19:05 被阅读36次

    Retrofit 2 源码分析


    惯例从一个例子入手

    //使用Builder模式创建Retrofit对象
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
    
    //创建Service对象, 这里统称为Service, 其实是一个接口的描述
    GitHubService service = retrofit.create(GitHubService.class);
    
    //发起请求调用
    Call<List<Repo>> repos = service.listRepos("octocat");
    

    定义Service接口

    其实就是用元数据很清晰的描述一个HTTP请求以及参数等等

    public interface GitHubService {
      @GET("users/{user}/repos")
      Call<List<Repo>> listRepos(@Path("user") String user);
    }
    

    使用Builder模式创建Retrofit对象

    这里有两个点比较有趣, 为一些属性做了default处理, 一个是保护性拷贝

    public static final class Builder {
        private final Platform platform;
        private okhttp3.Call.Factory callFactory;
        private HttpUrl baseUrl;
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
        private Executor callbackExecutor;
        private boolean validateEagerly;
        
        
        ...
        
         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();
          }
    
          //注意看这里, 这里用了个保护性拷贝创建两个list 比较有趣。
          // Make a defensive copy of the adapters and add the default Call adapter.
          List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
          
          //这里后续会看到他添加了默认的CallAdapterFactory
          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);
        }
        
    

    创建Service的对象, 动态代理模式

    如果说前面的GitHub 接口是对一个请求的描述, 那么create方法就是要生成这个被描述请求的对象。
    通过create 方法, 动态代理GitHub这个接口, 解析Annotation, 生成调用对象等

    public <T> T create(final Class<T> service) {
        //验证service 是interface 并且, 不能继承其他接口
        Utils.validateServiceInterface(service);
        //是否急切的先执行loadServiceMethod
        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, Object... args)
                  throws Throwable {
                // 如果调用者的class对象是Object, 则执行默认的method 调用
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                if (platform.isDefaultMethod(method)) {
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                
                //这里可以认为是解析调用方法参数等, 生成serviceMethod对象
                ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                    
                //根据serviceMethod 最终实例化OkHttpCall 对象
                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                //调用callAdaper去生成Call对象, 这里传入的是okHttpCall, 最后会用到
                return serviceMethod.callAdapter.adapt(okHttpCall);
              }
            });
      }
    

    缓存ServiceMethod, 假设这个Service(比如Github)被解析过了会缓存起来

    看看这个loadServiceMethod, 首先检查serviceMethodCache, 这个cache是个ConcurrentHashMap,
    如果缓存不存在, 则利用 ServiceMethod.Builder生成一个ServiceMethod

      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;
      }
    

    总结上面的流程:


    image_1b3u27ohat9u1dfku2ub9crgt9.png-20kBimage_1b3u27ohat9u1dfku2ub9crgt9.png-20kB

    ServiceMethod 是怎么解析Method

    首先通过SeviceMethod.Builder 构建ServiceMethod

      Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
         
          //这里利用反射的方法获取方法的Annotation, 参数类型, 参数的Annotation
          this.methodAnnotations = method.getAnnotations();
          this.parameterTypes = method.getGenericParameterTypes();
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
        
        
     public ServiceMethod build() {
      //创建CallAdatper
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      //创建Response数据处理器
      responseConverter = createResponseConverter();
          ...
          
    

    创建CallAdapter, 首先通过反射获取method返回的类型

        private CallAdapter<T, R> createCallAdapter() {
          Type returnType = method.getGenericReturnType();
          if (Utils.hasUnresolvableType(returnType)) {
            throw methodError(
                "Method return type must not include a type variable or wildcard: %s", returnType);
          }
          if (returnType == void.class) {
            throw methodError("Service methods cannot return void.");
          }
          Annotation[] annotations = method.getAnnotations();
          try {
            //noinspection unchecked
            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);
          }
        }
    

    retrofit.callAdapter其实是遍历adapterFactories,调用adapterFactor.get()创建CallAdapter

      public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
          Annotation[] annotations) {
        checkNotNull(returnType, "returnType == null");
        checkNotNull(annotations, "annotations == null");
    
        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;
          }
        }
    

    默认的CallAdapterFactory与CallbackExecutor

    如果最开始初始化Retrofit时没有传adapterFactories, 则使用默认的CallAdapterFactory 和默认CallbackExecutor , 从下面代码可以看出, 默认的CallbackExecutor 是在主线程执行。

    
      static class Android extends Platform {
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
          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);
          }
        }
      }
    

    创建CallAdapter

    CallAdapter是由CallAdapterFactory生产的
    再来看下默认的CallAdapterFactory的实现
    get方法, 生成一个实现了CallAdapter接口的对象
    然后adapt又生成了Call对象
    简单点说就是CallAdapterFactory(制造CallAdapter对象)创建一个CallAdapter(适配Call的对象),传入callbackExecutor(怎么去执行, 比如在主线程执行), Factory 你可以自定义, CallAdapter也可以自定义, Executor也可以自定义, 非常灵活

    @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;
          }
    
          //调用adapt 方法, 实例化Call对象, 传入callbackExecutor
          @Override public Call<Object> adapt(Call<Object> call) {
            return new ExecutorCallbackCall<>(callbackExecutor, call);
          }
        };
      }
    

    CallAdapter 适配器模式

    CallAdapter是一个接口,他定义了

      //response body 转换为 java 对象时使用, 告诉Converter 转为什么类型
      Type responseType();
      //如何生成call
      T adapt(Call<R> call);
    

    Call也是个接口

      //异步调用
      void enqueue(Callback<T> callback);
    
      boolean isExecuted();
     
      //取消调用
      void cancel();
    
      boolean isCanceled();
    
      //原始的http请求
      Request request();
    

    再来看下默认的Call实现:

    
      static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;
    
        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    
        @Override public void enqueue(final Callback<T> callback) {
          if (callback == null) throw new NullPointerException("callback == null");
          //调用委托来异步请求, 这个委托就是就是最上面讲到的传入的OkhttpCall对象
          delegate.enqueue(new Callback<T>() {
            @Override public void onResponse(Call<T> call, final Response<T> response) {
              //这里的callbackExecutor 就是开始看到的默认的callbackExecutor
              //解释下, 当请求完成后, 调用callbackExecutor来执行逻辑
              //这里callbackExecutor 上面说过到的默认Execute, 即在主线程的handler里面处理响应结果
              callbackExecutor.execute(new Runnable() {
                @Override public void run() {
                  if (delegate.isCanceled()) {
                    // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                    callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                  } 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);
                }
              });
            }
          });
        }
      }
    

    所以说, 你可以自己实现一个CallApdater来实现处理调用的逻辑, 以及调用之后处理结果的逻辑
    很简单, 看下默认的ExecutorCallAdapterFactory 的实现就明白了
    首先

    final class ExecutorCallAdapterFactory extends CallAdapter.Factory
    

    然后 重写get方法

      @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);
          }
        };
      }
    
      static final class ExecutorCallbackCall<T> implements Call<T> {
    

    adapt里面 实例化一个Call 对象, Call对象的实现如下
    实现Call<T>接口, 重写enqueue方法, 剩下的想怎么玩就怎么玩

      static final class ExecutorCallbackCall<T> implements Call<T>
          @Override public void enqueue(final Callback<T> callback) {
    

    整个流程基本上已经剖析完成, 总结下


    image_1b410r131p0q13t51mr812cjb4113.png-33.8kBimage_1b410r131p0q13t51mr812cjb4113.png-33.8kB

    一些有趣的小点:
    比如使用unmodifiableList 做保护性copy, 说白了就是让他list不可变

        this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
        this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
    

    涉及到的反射API:

    method.getDeclaringClass()          //获取该方法调用者的class对象
    method.getAnnotations()             //获取该方法所有的Annotation
    method.getDeclaringClass()          //获取该方法调用者的class对象
    method.getGenericParameterTypes();  //获取参数类型
    method.getParameterAnnotations();   //或者参数的Annotation
    

    相关文章

      网友评论

          本文标题:retrofit 源码分析

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