Retrofit2源码解读

1、基本介绍:

1.1、重要类介绍:

call:

  • 创建Http网络请求。
  • 提供了同步异步请求方法:execute()、enqueue()。
  • 生成Request对象,返回请求结果对象。

callFactory:

  • Call的工厂类。
  • 默认直接new OkHttpClient()。
  • 如果你需要对okhttpclient进行详细的设置,需要构建OkHttpClient对象,然后传入。

CallAdapter:

  • 网络请求适配器:用于对Call进行转化,将默认的OkHttpCall转换为适合被不同平台来调用的网络请求执行器形式。
  • retrofit会通过运行时的不同平台,然后选择不同的CallAdapter。
  • 在Retrofit中提供了四种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory。
  • 该默认ExecutorCallAdapterFactory会使得Call在异步调用时在指定的 Executor线程上执行回调。

callAdapterFactories:

  • CallAdapter的工厂。

callbackExecutor:【切换线程】

  • 回调方法执行器:用来将回调传递到UI线程了【利用了Handler机制】。

converterFactories:【对数据对象进行转换】

  • 数据转换器工厂,该对象用于转化数据(可用于对请求数据、响应数据、注解参数数据进行转换)
  • responseBodyConverter():完成ResponseBody到实际的返回类型的转化。
  • requestBodyConverter ():完成对象到RequestBody的构造。
  • 一定要注意,检查type如果不是自己能处理的类型,记得return null (因为可以添加多个,你不能处理return null ,还会去遍历后面的converter).

ServiceMethod类:

  • 一个 ServiceMethod 对象对应于网络请求接口里的一个方法,用于将我们接口中的方法转化为一个Request对象。

2、具体流程:

2.1、 Retrofit的实例构建:【建造者模式】
Retrofit retrofit = new Retrofit.Builder()
              .baseUrl(请求地址)
              .addConverterFactory(GsonConverterFactory.create()) //添加数据转换器
              .build();
public Builder() {
      //查看当前的运行平台,支持Android、Java8平台
      this(Platform.get());
  }

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

    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
      callFactory = new OkHttpClient();
    }

      //用来将回调传递到UI线程
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
      callbackExecutor = platform.defaultCallbackExecutor();
    }

      //将网络请求对象Call进行平台适配。
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.adapterFactories);
    callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    //数据转化器
    List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

    return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
        callbackExecutor, validateEagerly);
  }
2.2、retrofit.create()来构建Call对象:【动态代理模式】
     GitHubService service =??retrofit.create(GitHubService.class);
     retrofit.Call<返回实体> call= service.请求的接口名称(请求参数);
【Retrofit.java】
  public <T> T create(final Class<T> service) {
      Utils.validateServiceInterface(service);

          // 判断是否需要提前验证:
                  1. 给接口中每个方法的注解进行解析并得到一个ServiceMethod对象.
                  2. 以Method为键将该对象存入LinkedHashMap集合中.
                  3.  特别注意:如果不是提前验证则进行动态解析对应方法,得到一个ServiceMethod对象,最后存入到LinkedHashMap集合中,类似延迟加载(默认)

      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, @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);
              }
              ServiceMethod<Object, Object> serviceMethod =
                  (ServiceMethod<Object, Object>) loadServiceMethod(method);
              OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
              return serviceMethod.adapt(okHttpCall);
            }
          });
    }
• 根据我们的method将其包装成ServiceMethod.
• 通过ServiceMethod和方法的参数构造retrofit2.OkHttpCall对象。
• 通过serviceMethod.adapt()方法,将OkHttpCall进行代理包装。
2.2.1、ServiceMethod serviceMethod = loadServiceMethod(method):
 # Retrofit.class
  //loadServiceMethod(method)负责加载 ServiceMethod
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
      ServiceMethod<?, ?> result = serviceMethodCache.get(method);
      if (result != null) return result;
      // 设置线程同步锁
      synchronized (serviceMethodCache) {
        // 创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例 
        // 若没缓存,则通过建造者模式创建 serviceMethod 对象
        result = serviceMethodCache.get(method);
        if (result == null) {
          result = new ServiceMethod.Builder<>(this, method).build();
          serviceMethodCache.put(method, result);
        }
      }
      return result;
  }
# ServiceMethod.class
  public final class ServiceMethod {
          final okhttp3.Call.Factory callFactory; 
          final CallAdapter<?> callAdapter;  
          private final Converter<ResponseBody, T> responseConverter; 
          // Response内容转换器:负责把服务器返回的数据(JSON或者其他格式,由 ResponseBody 封装)转化为 T 类型的对象;
          private final HttpUrl baseUrl; // 网络请求地址  
          private final String relativeUrl; // 网络请求的相对地址  
          private final String httpMethod;   // 网络请求的Http方法  
          private final Headers headers;  // 网络请求的http请求头 键值对  
          private final MediaType contentType; // 网络请求的http报文body的类型  
          private final ParameterHandler<?>[] parameterHandlers;  
          // 方法参数处理器:负责解析每个方法里的参数,并在构造 HTTP 请求时设置参数;
          ServiceMethod(Builder<R, T> builder) {
              this.callFactory = builder.retrofit.callFactory();
              this.callAdapter = builder.callAdapter;
              this.baseUrl = builder.retrofit.baseUrl();
              this.responseConverter = builder.responseConverter;
              this.httpMethod = builder.httpMethod;
              this.relativeUrl = builder.relativeUrl;
              this.headers = builder.headers;
              this.contentType = builder.contentType;
              this.hasBody = builder.hasBody;
              this.isFormEncoded = builder.isFormEncoded;
              this.isMultipart = builder.isMultipart;
              this.parameterHandlers = builder.parameterHandlers;
            }
          ... 
  }
# ServiceMethod.Builder静态内部类
  Builder(Retrofit retrofit, Method method) {
    this.retrofit = retrofit;
    this.method = method;
    // 获取网络请求接口里的方法注解:PUT、GET ...
    this.methodAnnotations = method.getAnnotations();
    // 获取网络请求接口方法里的参数类型       
    this.parameterTypes = method.getGenericParameterTypes();  
    //获取网络请求接口方法里的参数注解:Body、Field ...    
    this.parameterAnnotationsArray = method.getParameterAnnotations();    
  }

  public ServiceMethod build() {
    callAdapter = createCallAdapter();    
    //根据网络请求接口方法的返回值类型和注解类型,从Retrofit对象中获取对应的网络请求适配器
    responseType = callAdapter.responseType();    
    //根据网络请求接口方法的返回值类型和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型
    responseConverter = createResponseConverter();    
    // 根据网络请求接口方法的返回值类型和注解类型,从Retrofit对象中获取对应的数据转换器

     for (Annotation annotation : methodAnnotations) {
      parseMethodAnnotation(annotation);
    }
    // 解析网络请求接口中方法的注解,包括:DELETE、GET、POST、HEAD、PATCH、PUT、OPTIONS、HTTP、retrofit2.http.Headers、Multipart、FormUrlEncoded

          int parameterCount = parameterAnnotationsArray.length;
          // 获取当前方法的参数数量

    parameterHandlers = new ParameterHandler<?>[parameterCount];
    for (int p = 0; p < parameterCount; p++) {
      Type parameterType = parameterTypes[p];
      Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
      // 为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型:这里的注解包括:Body、PartMap、Part、FieldMap、Field、Header、QueryMap、Query、Path、Url 

      parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
    } 
    return new ServiceMethod<>(this);
  }
  • callAdapter.responseType():返回的是我们方法的实际类型,例如:Call,则返回User类型,然后对该类型进行判断。

  • createResponseConverter():负责把服务器返回的数据(JSON或者其他格式,由 ResponseBody 封装)转化为 T 类型的对象。

  • 接下来就是对注解进行解析了,主要是对方法上的注解进行解析,那么可以拿到httpMethod以及初步的url.
  • 后面是对方法中参数中的注解进行解析,这一步会拿到很多的ParameterHandler对象,每一个参数创建一个ParameterHandler对象。
2.2.2、OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args):
  • 这里生成Call的代理执行类:OkHttpCall类,将call放入okhttp的请求队列中。
  • OkHttpCall类是OkHttp的包装类。
  • 创建了OkHttpCall类型的Call对象还不能发送网络请求,需要创建Request对象才能发送网络请求。
2.2.3、serviceMethod.callAdapter.adapt(okHttpCall):
 # ExecutorCallAdapterFactory.java
  @Override 
  public Call<Object> adapt(Call<Object> call) {
    return new ExecutorCallbackCall<>(callbackExecutor, 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;//把上面创建并配置好参数的OkhttpCall对象交给静态代理对象delegate.
      }
      ...
  }
2.3、发起网络请求:
  • 步骤1:对网络请求接口的方法中的每个参数利用对应ParameterHandler进行解析,再根据ServiceMethod对象创建一个OkHttp的Request对象
    1. 通过serviceMethod.callAdapter.adapt(okHttpCall)去调用ExecutorCallAdapterFactory.adapt()方法.
    2. 进一步调用OkHttpCall类的一系列方法去创建Request请求对象。
  • 步骤2:使用OkHttp的Request发送网络请求;
  • 步骤3:对返回的数据使用之前设置的数据转换器(GsonConverterFactory)解析返回的数据,最终得到一个Response对象
  • 步骤4:进行线程切换从而在主线程处理返回的数据结果
    【异步跟同步请求不同之处在于:异步请求会将回调方法交给回调执行器在指定的线程中执行】
2.3.1、同步请求:
 Response<JavaBean> response = call.execute();  
2.3.2、异步请求:
call.enqueue(new Callback<JavaBean>() {
    @Override
    public void onResponse(Call<JavaBean> call, Response<JavaBean> response) {
        if (response.isSuccessful()) {
            response.body().show();
        } else {
            try {
                System.out.println(response.errorBody().string());
            } catch (IOException e) {
                e.printStackTrace();
            } ;
        }
    }

    @Override
    public void onFailure(Call<JavaBean> call, IOException e){
      ...
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
retrofit2是一个用于Android和Java平台的类型安全的HTTP客户端库,它可以用来进行网络请求和数据交互。在retrofit2中,可以使用SSE(Server-Sent Events)来进行服务器推送的实现。 SSE是一种在客户端和服务器之间单向实时通信的技术,它允许服务器发送事件数据到客户端,而客户端则可以监听这些事件并做出相应的处理。在retrofit2中,可以通过定义一个接口来实现SSE的处理,如下所示: ```java public interface SSEService { @GET("/events") Call<ResponseBody> getEvents(); } ``` 在这个例子中,我们定义了一个SSEService接口,其中包含一个用于获取事件数据的GET请求。当调用这个接口时,retrofit2会使用OkHttp来建立连接并监听服务器发送的事件数据。 另外,为了处理服务器发送的事件数据,可以使用retrofit2的Call对象和Callback来实现。例如: ```java SSEService service = retrofit.create(SSEService.class); Call<ResponseBody> call = service.getEvents(); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { // 处理服务器发送的事件数据 } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 处理请求失败的情况 } }); ``` 通过使用retrofit2的SSE功能,可以很方便地实现客户端和服务器之间的实时事件推送和处理。这使得在Android和Java应用中,可以更加灵活和高效地处理服务器推送的事件数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值