IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Retrofit 源码解析 -> 正文阅读

[网络协议]Retrofit 源码解析

简介

一个用于Android和Java平台的类型安全的网络框架。Retrofit 是一个Square开发的类型安全的REST安卓客户端请求库。这个库为网络认证、API请求以及用OkHttp发送网络请求提供了强大的框架,底层对网络的访问默认也是基于OkHttp。

官网地址

依赖

implementation 'com.squareup.retrofit2:retrofit:2.9.0'

用法

基本用法

// 创建网络请求接口

interface Api {
    @GET("users/{user}/repos")
    fun listRepos(@Path("user") user:String):Call<List<Repo>>
}


val baseUrl = "https://api.github.com/"

val okHttpClient = OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(60, TimeUnit.SECONDS)
    .writeTimeout(90, TimeUnit.SECONDS)
    .build()
    
// 创建 Retrofit 的实例
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .client(okHttpClient)
    .build()

// 创建网络请求接口的实例,并调用接口中的方法获取 Call 对象
val api = retrofit.create(Api::class.java)
val call = api.listRepos("")    
// 同步请求
call.execute()
// 异步请求
call.enqueue(object :retrofit2.Callback<List<Repo>> {
      override fun onFailure(call: retrofit2.Call<List<Repo>>, t: Throwable) {}

      override fun onResponse(call: retrofit2.Call<List<Repo>>, response: retrofit2.Response<List<Repo>>) {}
   })

源码解析

创建 Retrofit 的实例

  • Retrofit 成员变量
// Retrofit.java 源码

  // ServiceMethod 的缓存,解析接口注解后相关信息(网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等)的存储
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new  ConcurrentHashMap<>();
  // 网络请求器工厂,默认为OkHttpClient
  final okhttp3.Call.Factory callFactory;
  // 网络请求的 url 地址
  final HttpUrl baseUrl;
  // 数据转换器工厂的集合
  final List<Converter.Factory> converterFactories;
  // 网络请求适配器的集合
  final List<CallAdapter.Factory> callAdapterFactories;
  // 回调函数的执行器,也就是回调函数执行的线程,Android 中默认为 MainThreadExecutor
  final @Nullable Executor callbackExecutor;
  // 一个标志位,用来判断是否需要加载 ServiceMethod
  final boolean validateEagerly;
  • Retrofit实例通过Builder(建造者)模式创建,接下来看下Builder的构造方法
// Retrofit.java 源码

public static final class Builder {
    //平台类型对象
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
      this.platform = platform;
    }

    public Builder() {
      this(Platform.get());
    }
    
    ...
}

可以看到构造方法Builder()内通过Platform.get()获取当前平台,一般是Android,当然也支持其他平台比如Java8等,get() 方法中又调用了 findPlatform() 方法。

// Platform.java 源码

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  // 判断当前运行平台
  private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //
        : new Platform(true);
  }

 
  @Nullable
  Executor defaultCallbackExecutor() {
    return null;
  }
  
  ...
  
  static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }

    @Override
    public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Nullable
    @Override
    Object invokeDefaultMethod(
        Method method, Class<?> declaringClass, Object object, Object... args) throws Throwable {
      if (Build.VERSION.SDK_INT < 26) {
        throw new UnsupportedOperationException(
            "Calling default methods on API 24 and 25 is not supported");
      }
      return super.invokeDefaultMethod(method, declaringClass, object, args);
    }

    static final class MainThreadExecutor implements Executor {
      // 主线程的handler
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override
      public void execute(Runnable r) {
      //通过Handler切换到主线程
        handler.post(r);
      }
    }
    
  }
  
}

可以看到,Builder()方法主要是用来查找当前运行的平台,Retrofit 支持 Android与Java平台。defaultCallbackExecutor()方法默认回调执行器是Null,如果当前运行平台是Android, 那么返回是MainThreadExecutor 执行器。

接下来,Builder如何配置url、网络请求器工厂、数据转换器工厂等

// Retrofit.java 源码
 
 // 配置OkHttpClient
 public Builder client(OkHttpClient client) {
      return callFactory(Objects.requireNonNull(client, "client == null"));
 }
 // 配置请求地址
 public Builder baseUrl(URL baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl.toString()));
 }
 
 public Builder baseUrl(String baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl));
 }
 
 public Builder baseUrl(HttpUrl baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
 }
 // 添加数据转换器工厂
 public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
 }
 
 // 添加请求适配器工厂
 public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
 }

生成Retrofit实例最后需要调用build(), 那么我们来看看该方法的实现

// Retrofit.java 源码

 public Retrofit build() {
      // baseUrl 是必须要设置的,否则报异常
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      // 如果没有设置 callFactory,则默认使用 OkHttpClient
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      //如果没有设置 callbackExecutor,则使用当前运行平台的默认 callbackExecutor
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 配置 CallAdapter.Factory 的集合,首先往集合中添加客户端设置的
      // 添加当前平台默认的 CompletableFutureCallAdapterFactory(Java8)与DefaultCallAdapterFactory
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // 配置 Converter.Factory 的集合
      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // 首先往集合中添加 BuiltInConverters
      converterFactories.add(new BuiltInConverters());
      // 然后添加客户端设置的 GsonConverterFactory
      converterFactories.addAll(this.converterFactories);
      // 最后添加当前平台默认的(OptionalConverterFactory)
      converterFactories.addAll(platform.defaultConverterFactories());
      
      // 调用 Retrofit 的构造函数来完成 Retrofit 中常量的赋值
      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }

上面代码使用了建造者模式去创建Retrofit的实例,创建的过程中主要配置了网络请求器工厂(callFactory)、网络请求的url地址(baseUrl)、数据转换器工厂的集合(converterFactories)、网络请求适配器工厂的集合(callAdapterFactories)、回调方法执行器(callbackExecutor)。

创建网络请求接口的实例

val api = retrofit.create(Api::class.java)

这部分用了动态代理以及外观模式创建了接口实例,以下是源码

// Retrofit.java 源码

public <T> T create(final Class<T> service) {
   // 验证是否是接口
    validateServiceInterface(service);
    return (T)
        // 通过动态代理创建接口的实例
        Proxy.newProxyInstance(
           //参数1:classLoader,被代理对象的类加载器
            service.getClassLoader(),
           // 参数2:接口类型数组,被代理对象需要实现的全部接口
            new Class<?>[] {service},
            // InvocationHandler,实现了 InvocationHandler 接口的对象
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable {
                // 如果该方法是 Object 的方法,那就直接调用
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

invoke()方法为InvocationHandler接口需要重写的方法,该方法里面会通过Java反射机制调用被代理对象的方法。该方法中参数1(proxy动态代理对象)对应例子中Api类,参数2(method 被代理对象的方法)对应例子中listRepos()方法,参数3(args被代理对象方法的参数)对应例子中listRepos()方法参数。

platform.isDefaultMethod()判断该方法是Java8默认方法,则执行该平台的默认方法。否则,会调用loadServiceMethod()方法得到ServiceMethod后再调用invoke()方法。

// Retrofit.java 源码

 ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        //返回 解析方法的注解、返回类型、参数的注解以及参数类型
        result = ServiceMethod.parseAnnotations(this, method);
        //将解析出的信息添加到ConcurrentHashMap中供之后用
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

首先会从 ServiceMethod 缓存集合中取出当前方法对应的 ServiceMethod,如果不为空,则直接返回。如果为空,则创建一个新的 ServiceMethod,即调用parseAnnotations()方法创建,然后再存到缓存集合中。

//ServiceMethod<T> 源码

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    // 调用 RequestFactory 的 parseAnnotations() 方法解析网络请求接口中的注解(关注点1)
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }
      //将接口方法的调用调整为HTTP请求(关注点2)
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

上面的方法,主要做了三件工作:首先,RequestFactory调用parseAnnotations()方法解析请求接口注解(解析方法、方法注解、参数类型、参数注解数组);接着,对返回类型进行判断;最后,HttpServiceMethod调用parseAnnotations()方法返回对应的请求。

  • 关注1
// RequestFactory 源码

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

// RequestFactory-Builder 源码
Builder(Retrofit retrofit, Method method) {
      // Retrofit 对象
      this.retrofit = retrofit;
      // 方法
      this.method = method;
      // 方法注解
      this.methodAnnotations = method.getAnnotations();
      // 参数类型
      this.parameterTypes = method.getGenericParameterTypes();
      // 参数注解数组
      this.parameterAnnotationsArray = method.getParameterAnnotations();
}  

// RequestFactory-Builder 源码
RequestFactory build() {
  
   for (Annotation annotation : methodAnnotations) {
        // 对请求方式(比如GET、POST)和请求地址进行解析
        parseMethodAnnotation(annotation);
   }
   
   // 省略部分判断...
   
   int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            // 对方法中的参数注解进行解析(比如@Query、@Part)
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
     }
    
    // 省略部分判断...
    
    // 网络请求接口中的注解已经解析出来了,然后创建 RequestFactory 对象并进行赋值后返回
    return new RequestFactory(this);
}

RequestFactory(Builder builder) {
    // 方法
    method = builder.method;
    // baseUrl
    baseUrl = builder.retrofit.baseUrl;
    // http 方法
    httpMethod = builder.httpMethod;
    // 相对路径
    relativeUrl = builder.relativeUrl;
    // 请求头,没有设置,默认为 null
    headers = builder.headers;
    // contentType,没有设置,默认为 null
    contentType = builder.contentType;
    // hasBody,没有设置,默认为 false
    hasBody = builder.hasBody;
    // isFormEncoded,没有设置,默认为 false
    isFormEncoded = builder.isFormEncoded;
    // isMultipart,没有设置,默认为 false
    isMultipart = builder.isMultipart;
     // 参数数组,例子中没有传参数,所以为 null
    parameterHandlers = builder.parameterHandlers;
    // 是否kotlin协程中挂起的函数
    isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
  }
  • 关注2
// HttpServiceMethod 源码

 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    ...
    //获取方法注解
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      ...
    } else {
      //网络请求方法的返回值类型就是请求适配器的类型
      adapterType = method.getGenericReturnType();
    }

    // 根据网络请求接口中的返回类型与注解
    // 获取相对应的网络请求适配器(CallAdapter)
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
     // 获取响应类型
    Type responseType = callAdapter.responseType();
    
    // 根据网络请求接口中的返回类型与注解获取相对应的数据转换器(Converter)
     Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
     // 获取网络请求器工厂(okhttp3.Call.Factory)
     okhttp3.Call.Factory callFactory = retrofit.callFactory;
     
     if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    }
    ...
}

抽象类HttpServiceMethod调用parseAnnotations()方法用来获取相对应的网络请求适配器(CallAdapter)、数据转换器(Converter)与网络请求器工厂(okhttp3.Call.Factory),最后再通过这些来创建HttpServiceMethod对象进行返回,CallAdapted类继承自HttpServiceMethod类,并实现adapt()抽象方法,而HttpServiceMethod继承自ServiceMethod。通过分析上面的源码可知,retrofit的create()方法中loadServiceMethod(method)方法实际上返回就是HttpServiceMethod对象。

现在loadServiceMethod方法()执行流程分析完毕,接着调用invoke()方法。

// create ()方法最后调用invoke 方法
loadServiceMethod(method).invoke(args);

// ServiceMethod 源码
abstract T invoke(Object[] args);

// HttpServiceMethod 源码
 @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    // call 类型为OkHttpCall
    return adapt(call, args);
  }
  
// 抽象类HttpServiceMethod 的abstract adapt()
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);

//CallAdapted继承了HttpServiceMethod
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;

    CallAdapted(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, ReturnT> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }
  //adapt方法的实现,调用callAdapter的adapt方法
    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);
    }
  }
  
// DefaultCallAdapterFactory 源码
@Override
  public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;

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

      @Override
      public Call<Object> adapt(Call<Object> call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

从上面代码可以知道Retrofit中的Call实际是用的OkHttpCall。 adapt()方法返回的是 ExecutorCallbackCall,而 ExecutorCallbackCall 实现了Call 接口,这样就获取了Call 对象了,就可以调用 execute()与 enqueue()方法进行网络请求了。

invoke

// DefaultCallAdapterFactory-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) {
      Objects.requireNonNull(callback, "callback == null");
      // delegate 类型是OkHttpCall
      // 关注点
      delegate.enqueue(
          new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(
                  () -> {
                    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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }

  
    @Override
    public Response<T> execute() throws IOException {
      return delegate.execute();
    }
    
}

可以看出ExecutorCallbackCall是对Call的封装,它主要添加了通过callbackExecutor将请求回调到UI线程。ExecutorCallbackCall的enqueue方法执行在主线程,callbackExecutor就是Platfrom默认添加的MainThreadExecutor(Android环境中),所以callback.onResponse中随意更新UI。当我们得到Call对象后会调用它的enqueue方法,其实调用的是ExecutorCallbackCall的enqueue方法,从关注点可以看出ExecutorCallbackCall的enqueue方法最终调用的是delegate的enqueue方法。delegate从Retrofit的create方法的代码中我们知道它其实就是OkHttpCall。

同/异步请求数据

同步请求

// OkHttpCall 源码

 @Override
  public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
      // 创建OkHttp的call
      call = getRawCall();
    }

    if (canceled) {
      call.cancel();
    }
    // 解析OkHttp返回来的数据
    return parseResponse(call.execute());
  }
  
private okhttp3.Call getRawCall() throws IOException {
    okhttp3.Call call = rawCall;
    if (call != null) return call;

    // 如果这不是第一次尝试,请重新抛出先前的失败
    if (creationFailure != null) {
      if (creationFailure instanceof IOException) {
        throw (IOException) creationFailure;
      } else if (creationFailure instanceof RuntimeException) {
        throw (RuntimeException) creationFailure;
      } else {
        throw (Error) creationFailure;
      }
    }

    // Create and remember either the success or the failure.
    try {
      return rawCall = createRawCall();
    } catch (RuntimeException | Error | IOException e) {
      throwIfFatal(e); // Do not assign a fatal error to creationFailure.
      creationFailure = e;
      throw e;
    }
  }

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

上面execute中通过getRawCall获取okhttp3.Call,getRawCall中又通过createRawCall中的callFactory.newCall创建okhttp3.Call,newCall的入参是通过requestFactory.create创建的请求对象。

// RequestFactory 源码

okhttp3.Request create(Object[] args) throws IOException {
    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args.length;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException(
          "Argument count ("
              + argumentCount
              + ") doesn't match expected count ("
              + handlers.length
              + ")");
    }
    // 通过http方法、请求地址、请求头等构建Request
    RequestBuilder requestBuilder =
        new RequestBuilder(
            httpMethod,
            baseUrl,
            relativeUrl,
            headers,
            contentType,
            hasBody,
            isFormEncoded,
            isMultipart);

    ...

    List<Object> argumentList = new ArrayList<>(argumentCount);
    for (int p = 0; p < argumentCount; p++) {
      argumentList.add(args[p]);
      handlers[p].apply(requestBuilder, args[p]);
    }
    // 通过Builder模式返回request
    return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
  }

接下来就是解析响应回来的数据了,点击 parseResponse() 方法进去看看

// OkHttpCall 源码

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse =
        rawResponse
            .newBuilder()
            .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
            .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }
    
    
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      // 通过设置的 Converter 将响应的数据解析成相应的实体类返回的
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

// GsonResponseBodyConverter 源码
@Override
  public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      // 通过Gson 转换相应实体类
      T result = adapter.read(jsonReader);
      if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
        throw new JsonIOException("JSON document was not fully consumed.");
      }
      return result;
    } finally {
      value.close();
    }
  }

异步请求

// OkHttpCall 源码

@Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(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 {
        // 使用了OkHttp的Call
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

    // call 是 okhttp3.Call 类型的,
    // 所以 enqueue() 就是 OkHttp 中的方法了,所以底层实际还是通过 OkHttp 进行网络请求
    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) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }

          @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) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
  }
小结

这一步的同步与异步请求其实底层分别调用的是OkHttp的同步与异步请求方法,然后通过我们设置的数据转换器(Converter)将响应的数据解析成相应的实体类返回。同步请求会直接返回,异步请求则会切换到主线程再进行返回。

总结

  • 创建网络请求接口

这一步主要是配置 HTTP 请求需要的各种参数,例如 HTTP 请求方法、请求头、请求参数、请求地址等。

  • 创建 Retrofit 的实例

这一步是通过建造者模式来创建 Retrofit 的实例,创建的过程中主要配置了网络请求器工厂(callFactory)、网络请求的 url地址(baseUrl)、数据转换器工厂的集合(converterFactories)、网络请求适配器工厂的集合(callAdapterFactories)、回调方法执行器(callbackExecutor)

  • 创建网络请求接口的实例,并调用接口中的方法获取 Call 对象

这一步是通过动态代理模式来创建网络请求接口的实例,然后再调用网络请求接口中的方法来执行动态代理中的 invoke() 方法。这一步的作用主要是解析网络请求接口中方法上的注解、参数、获取返回类型等,也就是将网络请求接口中的方法解析成 HTTP 请求需要的各种参数。这里使用动态代理的好处是可以将网络请求接口的所有方法的调用都会集中转发到InvocationHandler 接口的 invoke()方法中,方便集中进行处理。

  • 进行网络请求

这一步的同步与异步请求其实底层分别调用的是 OkHttp 的同步与异步请求方法,然后通过我们设置的数据转换器(Converter)将响应的数据解析成相应的实体类返回。同步请求会直接返回,异步请求则会切换到主线程再进行返回。

流程图

资料

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-17 13:06:20  更:2021-11-17 13:06:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:28:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码