专栏名称: 走了
Android攻城狮
目录
相关文章推荐
什么值得买  ·  7499元起,华为发布阔折叠手机Pura ... ·  昨天  
什么值得买  ·  16种春日野菜尝鲜!打开看看你吃过几个? ·  昨天  
爱猫之和高Y家打官S版  ·  赚点公证费才行,好久不在公众号发冻干了,自己 ... ·  昨天  
爱猫之和高Y家打官S版  ·  赚点公证费才行,好久不在公众号发冻干了,自己 ... ·  昨天  
知乎日报  ·  持续刷短视频,真的会导致大脑生锈吗? ·  2 天前  
每日商报  ·  简约百搭,春天最需要的单品来了! ·  2 天前  
每日商报  ·  简约百搭,春天最需要的单品来了! ·  2 天前  
51好读  ›  专栏  ›  走了

Retrofit流程解析

走了  · 掘金  ·  · 2021-02-19 15:24

正文

阅读 7

Retrofit流程解析

Retrofit

Retrofit通过组合各种设计模式,封装网络请求接口的框架,具体的请求交给Okhttp去完成。

简单实现

Retrofit对象的配置需要数据序列化、线程调度、适配器等一系列的配置。具体配置可以自由设置,需要注意的是配置数据转换器时,要指定对应的转换器。不然数据序列化时可能会报错。

val client = OkHttpClient.Builder()
        .addInterceptor(LoggingInterceptor())
        .build()

val retrofit = Retrofit.Builder()
        .client(client)
        .baseUrl(HttpService.HttpUrl.url)
        .addCallAdapterFactory(KotlinCallAdapterFactory())
        .addConverterFactory(GsonConverterFactory.create())
        .addConverterFactory(SimpleXmlConverterFactory.create())
        .addConverterFactory(JaxbConverterFactory.create())
        .build()

fun request() {
    retrofit.create(HttpService::class.java)
            .request1()
            .enqueue(object : Callback<ResponseData<List<WxArticle>>> {
                override fun onResponse(call: Call<ResponseData<List<WxArticle>>>, response: Response<ResponseData<List<WxArticle>>>) {
                    Log.i("MDY", "onResponse=" + Thread.currentThread().name)
                    Log.i("MDY", "onResponse: " + response.body().toString())
                }

                override fun onFailure(call: Call<ResponseData<List<WxArticle>>>, t: Throwable) {
                    Log.i("MDY", "onFailure: ")
                }
            })
}

复制代码

Retrofit创建后,具体的网路请求需要调用 create 方法,动态生成一个代理类来实现对应的网络请求。

create

Android中创建一个委托类Service时,由于Service是一个接口,请求方法一定是 public abstract 类型,所以Retrofit中 create 方法创建的动态代理类在调用Service中对应的请求方法时,最终会执行到 loadServiceMethod 方法中:

  ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;
    //同步锁,防止ServiceMethod多次创建
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        //解析Method
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
复制代码

Retrofit中使用一个Map集合来保存已经解析过的请求方法并封装为对应的实现类 ServiceMethod :

private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>()
复制代码

若请求接口时第一次被调用,会通过 ServiceMethod parseAnnotations 来解析方法。首先会调用 RequestFactory parseAnnotations 方法解析方法的注解、参数注解、返回类型等:

  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    //......判断返回类型是否合法
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }
复制代码

HttpServiceMethod 本身也是一个抽象类, parseAnnotations 方法中会获取对应的 CallAdapter、Converter和callFactory 对象,最后创建一个CallAdapted对象返回。

createCallAdapter

  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    try {
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }
复制代码

调用Retrofit的 callAdapter 方法,最终会回调到我们在创建Retrofit时传入的 CallAdapterFactory 中,并调用对应的 get 方法获取 CallAdapter 对象。

createResponseConverter

  private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create converter for %s", responseType);
    }
  }
复制代码

调用Retrofit的 responseBodyConverter 方法,最终会回调到我们在创建Retrofit时传入的 Converter.Factory 中,并调用对应的 responseBodyConverter 方法获取 Converter<ResponseBody, ?> 对象。在后面的 OkHttpCall 中获取响应体后会调用已创建的 Converter 来序列化数据。

callFactory

okhttp3.Call.Factory callFactory = retrofit.callFactory;
复制代码

Call.Factory就是我们传递到Retrofit中的OkhttpClient对象。

CallAdapted

ServiceMethod HttpServiceMethod 都是抽象类,我们需要的是一个具体的实现类,所以CallAdapted来了。CallAdapted继承自 HttpServiceMethod 并保存了以下对象:

  • requestFactory 解析请求方法后的数据保存类。
  • callFactory OkhttpClient对象,用于具体的网络请求。
  • responseConverter 数据转换器,用于序列化请求返回的响应。
  • callAdapter 调用适配器,或区域一个call的对象,可以实现请求的发起和线程的调度。

执行到了这里,我们回到最开始的 create 方法中,当通过动态代理调用请求方法时,执行到 loadServiceMethod 最终会获取到一个 CallAdapted 对象。紧接着调用 invoke 方法, CallAdapted 中并没有实现该方法,具体的在 HttpServiceMethod 中:

  @Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return






请到「今天看啥」查看全文


推荐文章