Retrofit

Retrofit 实现一次网络请求流程

  1. 定义抽象网络请求接口
  2. new Retrofit对象。配置baseUrl。
  3. 调用retrofit.create函数,生成代理类对象。GitHubService service = retrofit.create(GitHubService.class)
  4. 调用抽象网络接口对象,生成retrofit2.Call对象。这个对象的默认实际类型是retrofit2.DefaultCallAdapterFactory.ExecutorCallbackCall
  5. 调用retrofit2.Call#execute发起同步网络请求, 或者调用 retrofit2.Call#enqueue发起异步网络请求。

官网wiki

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:retrofit-converters:2.8.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:retrofit-adapters:2.8.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

生成Call<T>对象 时序图

在这里插入图片描述

Retrofit 小的语法规则

  • 不支持再网络请求Interface接口中声明泛型。源码位置:Retrofit#validateServiceInterface(Class<?> service)
  • 动态请求参数只能通过@Query注解。不支持在GET、POST、HTTP、HEAD....等注解中通过{ }定义动态参数,然后在接口函数中通过@Path注解赋值。
  • 网络请求接口Interface,只允许有一个Retrofit的有效注解,不支持多注解情况。
  • 网络请求接口Interface接口中的函数禁止void类型的返回值。
  • 默认情况下网络请求的异步callback是在主线程中执行的。源码参考:Platform.Android.MainThreadExecutorDefaultCallAdapterFactory#callbackExecutor

设计模式

  • 建造者模式 Retrofit.Builder, RequestFactory.Builder
  • 工厂模式。Converter.Factory, CallAdapter.Factory
  • 适配器模式。CallAdapter#adapt, retrofit2.adapter.rxjava3.RxJava3CallAdapter。适配器内的委托:DefaultCallAdapterFactory.ExecutorCallbackCall#delegate
  • 动态代理模式。https://blog.csdn.net/followYouself/article/details/120242621

Platform.java

  • Platform#defaultCallAdapterFactories 函数生成默认CallAdapter
  • Platform#defaultConverterFactories 函数生成默认Converter
  • Platform.Android.MainThreadExecutor 类,默认callback回调在MainLooper中执行。
Platform#Platform 构造函数解析
  • Platform构造函数初始化为Android平台。Android平台的判断条件"Dalvik".equals(System.getProperty("java.vm.name")).
  • 通过MethodHandles.Lookup调用非public的interface,调用interface中的default方法。
  • 通过反射Lookup的private构造函数,获取Lookup的实例对象。因为默认通过MethodHandles.lookup()的静态方法生成Lookup实例对象,此对象是禁止访问私有方法的。
  • 一句话解释:MethodHandlesLookup是一套相比于传统反射框架性能更高更快的反射接口,但传统的反射框架是更通用且开发者更容易实现。
  • MethodHandlesLookup实现参考Android源码: /Android_Q/libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java

Retrofit.Builder.java

  • Retrofit.Builder#callFactory默认值是okhttp3.OkHttpClient。 在Retrofit.Builder#build函数中赋默认值。可以通过retrofit2.Retrofit.Builder#client配置
  • Retrofit.Builder#callbackExecutor默认值是Platform.Android.MainThreadExecutor。在Retrofit.Builder#build函数中赋默认值。

RequestFactory.java 网络请求接口解析

  • okhttp3.Request对象的构造工厂。用于解析注解和生成request对象。
  • 自定义的网络请求接口的注解(函数注解和函数参数注解)是在这个类中解析完成的。主要是两个函数:解析函数注解parseMethodAnnotation 和 解析函数入参注解parseParameter
  • RequestFactory#create会根据解析的网络接口和相关注解,加上传入的参数,生成请求对象okhttp3.Request
RequestFactory.Builder#build函数
  1. parseMethodAnnotation 解析函数注解。并且使用正则解析出函数注解中的动态参数,例如:{user},解析出user字符串。
  2. parseParameter 解析函数参数。每个函数参数只允许有一个Retrofit注解。
  3. 构造RequestFactory实例。
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
private static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";  // 匹配以大小写字母开始的,含有字母、数字、下划线横线的字符串
 // 在PARAM基础上,匹配带{}的字符串。例如{user}、{name}等。并且将PARAM作为子元组。
private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}"); // 两个反斜杠来加大括号来标示匹配 大括号字符串
private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);

CallAdapter.java

  • 默认的CallAdapter.FactoryCompletableFutureCallAdapterFactoryDefaultCallAdapterFactory。Retrofit的build函数中调用函数Platform#defaultCallAdapterFactories添加到List列表。
  • DefaultCallAdapterFactory对应的网络接口返回值类型是Call<自定义对象类型>,CompletableFutureCallAdapterFactory对应的网络接口返回值类型 CompletableFuture<自定义对象类型>
DefaultCallAdapterFactory.ExecutorCallbackCall
  • ExecutorCallbackCall: 这是调用interface的接口,返回的Call对象的实际类型。
  • ExecutorCallbackCall实现了retrofit2.Call接口,类的内部实现委托到retrofit2.OkHttpCall对象上。通过OkHttpCall和okhttp进行网络交互。
  • ExecutorCallbackCall#delegate这个成员变量,默认的实际类型是 retrofit2.OkHttpCall
Call<List<Repo>> repos = service.listRepos("octocat"); // ExecutorCallbackCall 类型

OkHttpCall.java

  • 这个类是Retrofit与okhttp3交互的核心类。实现了retrofit2.Call接口。
  • OkHttpCall集成了RequestFactory(请求对象工厂),Object[] args函数入参,okhttp3.Call.Factory callFactory网络请求工厂(默认OkHttpClient),用callFactory来生成okhttp3.Call rawCallConverter<ResponseBody, T> responseConverter网络返回对象coverter对象。
  • enqueueexecute网络请求操作,最终都是通过OkHttpCall委托到okhttp3 上实现。retrofit2.OkHttpCall#rawCall是实际okhttp3.Call对象。
  • OkHttpCall#createRawCall 函数会调用callFactroy.newCall生成一个okhttp3.Call对象,用于发起网络请求。callFactroy实际是okhttp3.OkHttpClient对象。
  • okhttp3.OkHttpClient实现了okhttp3.Call.Factory接口,实现接口方法okhttp3.Call.Factory#newCall,用于生成okhttp3.Call对象。
private okhttp3.Call createRawCall() throws IOException {
  okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

默认生成的Call对象

OkHttpCall集成了主要模块,对接OkHttp

Converter.java

  • Converter<?, RequestBody> requestBodyConverter 接口的意义是网络请求时,将自定义的?对象类型转换为okhttp3所需要的RequestBody类型。
  • Converter<ResponseBody, ?> responseBodyConverter 接口的意义是将okhttp3网络请求返回的ResponseBody对象转换为 ?目标类型。
  • 默认的ConverterFactory类型是BuiltInConverters,只支持ResponseBody.class或者Void.class作为返回值类型。BuiltInConverters单词字面意思:内部的已经构建好的Converter类,里面包含了多种默认Convert对象。
  • 在不添加自定义的ConverterFactory时,是无法将网络请求的返回字符串转换为自定义对象的。
  • 常用的Factory类型有GsonConverterFactory

一次网络请求的函数执行流程

  • Call.enqueue(Callback) --> OkHttpCall#enqueue(Callback) --> OkHttpCall#createRawCall --> RequestFactory#create --> okhttp3.Call#enqueue(Callback) --> okhttp发起网络请求 --> 回调 okhttp3.Callback#onResponse --> OkHttpCall#parseResponse --> 调用默认converter BuiltInConverters.BufferingResponseBodyConverter#convert --> Callback#onResponse

注意点

URL路径:? 问号后不允许动态参数{}
  • 动态请求参数只能通过@Query注解。不支持在GET、POST、HTTP、HEAD....等注解中通过{ }定义动态参数,然后在接口函数中通过@Path注解赋值。
  • 参考:retrofit2.RequestFactory.Builder#parseHttpMethodAndPath
public interface GitHubService {
  @GET("users/{user}/repos?id={id}&nickName={nickName}")  // 此处在问号后配置请求参数id和nickName的方式是被禁止的。
  Call<List<Repo>> listRepos(@Path("user") String user, @Path("id") String id, @Path("nickName") String nickName);
}
// 源码:retrofit2.RequestFactory.Builder#parseHttpMethodAndPath

// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
  // Ensure the query string does not have any named parameters.
  String queryParams = value.substring(question + 1);
  Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
  if (queryParamMatcher.find()) {
    throw methodError(method, "URL query string \"%s\" must not have replace block. "
        + "For dynamic query parameters use @Query.", queryParams);
  }
}
网络请求Interface接口的入参不允许多个Retrofit注解
  • 函数的入参只允许一个有效Retrofit注解。例如:@Path@Query不能同时注解一个函数参数。
  • Multiple Retrofit annotations found, only one allowed
  • 参考源码:retrofit2.RequestFactory.Builder#parseParameter
private @Nullable ParameterHandler<?> parseParameter(
    int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
  ParameterHandler<?> result = null;
  if (annotations != null) {
    for (Annotation annotation : annotations) {
      ParameterHandler<?> annotationAction =
          parseParameterAnnotation(p, parameterType, annotations, annotation);
      if (annotationAction == null) {
        continue;
      }
      if (result != null) {  // 已经解析过一个注解了,不允许再次解析
        throw parameterError(method, p, "Multiple Retrofit annotations found, only one allowed.");
      }
      result = annotationAction;
    }
  }
}

面向抽象、接口编程

接口 or 抽象类实现
CallDefaultCallAdapterFactory.ExecutorCallbackCall,
OkHttpCall
Converter<F, T>BuiltInConverters.RequestBodyConverter implements Converter<RequestBody, RequestBody>,
BuiltInConverters.BufferingResponseBodyConverter implements Converter<ResponseBody, ResponseBody>,
retrofit2.converter.gson.GsonRequestBodyConverter implements Converter<T, RequestBody>,
retrofit2.converter.gson.GsonResponseBodyConverter implements Converter<ResponseBody, T>
Converter.Factoryretrofit2.BuiltInConverters, retrofit2.converter.gson.GsonConverterFactory
CallAdapter<R, T>DefaultCallAdapterFactory#get new CallAdapter<Object, Call<?>>,
retrofit2.adapter.rxjava3.RxJava3CallAdapter implements CallAdapter<R, Object>
CallAdapter.Factoryretrofit2.DefaultCallAdapterFactory,
retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
ServiceMethodHttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod
HttpServiceMethod<ResponseT, ReturnT>HttpServiceMethod.CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT>
okhttp3.Callokhttp3.RealCall
okhttp3.Call.Factoryokhttp3.OkHttpClient

反射相关方法

Method
  • getTypeParameters: 按照声明顺序返回函数中声明的泛型变量,返回值类型是个数组。
  • getGenericParameterTypes: 获取函数的入参列表。返回Type[]类型的数组。返回值会体现出泛型相关信息。
  • getParameterTypes: 获取函数的入参列表,返回的是class[] 类型的数组。返回值不会体现泛型相关信息。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Retrofit是一个非常流行的网络请求库,支持HTTP和HTTPS协议。在使用Retrofit进行HTTPS请求时,需要进行一些配置,以确保请求的安全性。下面是使用Retrofit进行HTTPS请求的步骤: 1.在build.gradle文件中添加Retrofit和OkHttp的依赖: ```gradle implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.okhttp3:okhttp:4.9.0' ``` 2.创建OkHttpClient实例,并配置TLS: ```java OkHttpClient.Builder builder = new OkHttpClient.Builder(); ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_2) .cipherSuites( CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) .build(); builder.connectionSpecs(Collections.singletonList(spec)); OkHttpClient client = builder.build(); ``` 3.创建Retrofit实例,并将OkHttpClient实例传入: ```java Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://example.com/") .client(client) .build(); ``` 4.创建API接口,并使用@HTTPS注解指定请求的HTTPS证书: ```java public interface ApiService { @GET("/") @HTTPS(certificates = "cert.pem") Call<String> get(); } ``` 5.发送HTTPS请求: ```java ApiService apiService = retrofit.create(ApiService.class); Call<String> call = apiService.get(); Response<String> response = call.execute(); String result = response.body(); ``` 需要注意的是,以上步骤只是简单介绍了如何使用Retrofit进行HTTPS请求,实际使用中还需要根据具体情况进行配置

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值