Retrofit2源码解析02-创建Call

我们在获得了Retrofit对象后,通过create方法可以获得生成接口的代理对象。

    ApiService service = retrofit.create(ApiService.class);  

来看create方法

    public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    //如果validateEagerly为true,则进行预处理,提前创造一些MethodHandler对象在缓存中,默认为true。
    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 {
            // 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 serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
    }  

首先调用了Utils.validateServiceInterface(service);

    static <T> void validateServiceInterface(Class<T> service) {
        if (!service.isInterface()) {
          throw new IllegalArgumentException("API declarations must be interfaces.");
        }
        // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
        // Android (http://b.android.com/58753) but it forces composition of API declarations which is
        // the recommended pattern.
        if (service.getInterfaces().length > 0) {
          throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
        }
    }  

可以看到,如果传入的Class不是接口,或者这个Class有继承自其它接口,则抛出异常。

再来看create方法中的Proxy.newProxyInstance,可以看到,新new了一个invocationHandler。主要来看InvocationHandler

    new InvocationHandler() {
      private final Platform platform = Platform.get();
    
      @Override public Object invoke(Object proxy, Method method, Object... args)
          throws Throwable {
        //method.getDeclaringClass() 返回方法定义所在的类
        //如果method定义所在的类就是object,直接通过反射调用
        if (method.getDeclaringClass() == Object.class) {
          return method.invoke(this, args);
        }
        //只有Java8实现了这个方法,其它平台都是返回false
        if (platform.isDefaultMethod(method)) {
          return platform.invokeDefaultMethod(method, service, proxy, args);
        }
        //加载ServiceMethod (优先从缓存中获取)
        ServiceMethod serviceMethod = loadServiceMethod(method);
        //传入serviceMethod和args,创建OkHttpCall
        OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
        //会创建ExecutorCallbackCall,并传入OkHttpCall
        return serviceMethod.callAdapter.adapt(okHttpCall);
      }
    });  

如果method定义所在的类就是object,直接通过反射进行调用。如果不是,则会通过loadServiceMethod加载serviceMethod。获取ServiceMethod之后,创建一个OkHttpCall,并传入到serviceMethod的callAdapter.adapt()。

先来看下loadServiceMethod,这个会优先从缓存中获取,如果获取为null,则新创建一个serviceMethod,并存储到缓存中。

    ServiceMethod loadServiceMethod(Method method) {
        ServiceMethod result;
        synchronized (serviceMethodCache) {
          //优先从缓存中获取
          result = serviceMethodCache.get(method);
          if (result == null) {
            result = new ServiceMethod.Builder(this, method).build();
            serviceMethodCache.put(method, result);
          }
        }
        return result;
    }  

来看下serviceMethod是怎么被创建的。可以看到,

  1. 首先遍历获得合适的CallAdapter和responseConverter。
  2. 遍历method的注解,对请求方式(GET,POST)进行解析
  3. 遍历method传入参数的注解(@Query、@Part),进行解析
    public ServiceMethod build() {
      //会遍历adapterFactories列表中存储的CallAdapter.Factory,通过get方法返回CallAdapter对象,判断并返回一个合适的CallAdapter。
      //(也就是通过addCallAdapterFactory进行添加的列表)
      callAdapter = createCallAdapter();
      //得到返回数据的真实类型
      responseType = callAdapter.responseType();
      //...
      //遍历converterFactories列表中存储的Converter.Factory,通过responseBodyConverter方法返回Converter方法,判断并返回一个合适的Converter用来转换对象。  
      //(也就是通过addConverterFactory进行添加的列表)
      responseConverter = createResponseConverter();
      //遍历method的注解,调用parseMethodAnnotation对请求方式(比如GET、POST)和请求地址进行解析
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      //...
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }
    
        //对方法中的参数注解进行解析 (比如@Query、@Part)  
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
    
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      //...
      return new ServiceMethod<>(this);
    }

createCallAdapter和createResponseConverter的代码逻辑类似,以createCallAdapter为例。
首先会获取Type和注解数组,然后调用callAdapter,最终,通过Type和注解数组获取相应的CallAdapter,并返回。

    private CallAdapter<?> createCallAdapter() {
      //获取method的Type (java反射)
      Type returnType = method.getGenericReturnType();
      //...
      //获取method的注解数组
      Annotation[] annotations = method.getAnnotations();
      try {
        return retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) {
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }
    
    public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
    }
    
    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;
            }
        }
    }  

至此,ServiceMethod就初始化完毕了。

再来看之前InvocationHandler中的serviceMethod.callAdapter.adapt()

    ServiceMethod serviceMethod = loadServiceMethod(method);
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    return serviceMethod.callAdapter.adapt(okHttpCall);

调用loadServiceMethod之后,会先创建一个OkHttpCall,这个的构造方法里面只是进行了赋值操作。

    OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
        this.serviceMethod = serviceMethod;
        this.args = args;
    }  

之后,会调用serviceMethod.callAdapter.adapt()
我们在前一篇文章里面讲过,serviceMethod.callAdapter是用作将OkHttp的call对象转化为需要的对象,比如默认的ExecutorCallAdapterFactory,又比如转化为RxJava的Observable的RxJavaCallAdapterFactory。

这里来看ExecutorCallAdapter.Factory

    @Override public <R> Call<R> adapt(Call<R> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
   }  

可以看到新new了一个ExecutorCallbackCall

    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");
        
          delegate.enqueue(new Callback<T>() {
            @Override public void onResponse(Call<T> call, final Response<T> response) {
              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);
                }
              });
            }
          });
        }  
        
        //...
    }  

可以看到ExecutorCallbackCall是对Call的封装,主要通过callbackExecutor(这个是在Retroft构建的时候创建的,android平台的默认的是MainThreadexecutor,主要是将runnable回调到主线程执行),在主线程中执行runnable。

而ExecutorCallbackCall继承自Retort的Call,enqueue中,会通过delegate.enqueue进行调用,这里的delegate是OkHttpCall。回调结果中,会去调用到主线程,然后通过callback进行回调。

总结

retrofit.create方法的内部会创建一个动态代理对象并返回,真正的执行者是这个动态代理对象。

  1. 如果method定义所在的类就是object,直接通过反射调用。
  2. 加载ServiceMethod(优先通过缓存)
    3. 会遍历并选用合适的callAdapter和responseConverter
    4. callAdapter:将Call对象转化的合适执行类,比如RxJavaCallAdapterFactory
    5. responseConverter: 转化数据对象,比如GsonConverterFactory
    3. 会解析method和method传参的注解,比如@Get、@Query
  3. 获得serviceMethod后,会创建OkHttpCall
  4. 调用serviceMethod.calladapter.adapt(okhttpcall),并返回Retroft的Call方法。

serviceMethod.calladapter.adapt深入

这里的calladapter可以自己设置,比如RxJavaCallAdapterFactory,这里以默认的ExecutorCallAdapterFactory为例。

当调用Retrot的Call的enqueue的时候,交由delegate这个okhttp代理对象执行,并在返回结果中,先回调到主线程,执行callback的相关方法。

其他

文中的Retrfot版本为Retrfot2.1.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
retrofit-spring-boot-starter是一个用于整合Retrofit库和Spring Boot的starter项目,它可以简化在Spring Boot中使用Retrofit的配置和使用。 以下是retrofit-spring-boot-starter的使用方法: 1. 在你的Spring Boot项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.github.lianjiatech</groupId> <artifactId>retrofit-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> ``` 2. 创建一个接口,用于定义Retrofit的API接口。例如: ```java import retrofit2.http.GET; import retrofit2.http.Path; public interface MyApi { @GET("/users/{username}") User getUser(@Path("username") String username); } ``` 3. 在你的Spring Boot应用程序中,使用`@Autowired`注解将Retrofit的API接口注入到你的代码中。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import retrofit2.Retrofit; @Service public class MyService { private final MyApi myApi; @Autowired public MyService(Retrofit retrofit) { this.myApi = retrofit.create(MyApi.class); } public User getUser(String username) { return myApi.getUser(username); } } ``` 4. 现在你可以在你的代码中使用`MyService`来调用Retrofit的API接口了。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { private final MyService myService; @Autowired public MyController(MyService myService) { this.myService = myService; } @GetMapping("/users/{username}") public User getUser(@PathVariable String username) { return myService.getUser(username); } } ``` 以上是retrofit-spring-boot-starter的基本用法。你可以根据自己的需求进行配置和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氦客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值