Retrofit2源码学习之流程详解

综述

Retrofit到一个实际请求/响应的过程包括

  • 创建ServiceMethod,调用ServiceMethod.build()
  • 调用OkHttpCall(ServiceMethod,args)创建OkHttpCall对象,
  • 调用 CallAdapter.adapt(okHttpCall)创建关联执行器Executor和Call的应用层Call类,Android默认为ExecutorCallbackCall

源码研究

  • 创建ServiceMethod

ServiceMethod.build()

  public ServiceMethod build() {
      //通过Retrofit.nextCallAdapter获取callAdapter,有自定义就用自定义,没有就用默认ExecutorCallAdapterFactory
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      //返回类型验证
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      //通过Retrofit.nextResponseBodyConverter处理转换异常,获得自定义转换器
      responseConverter = createResponseConverter();
      //解析自定义的注解成URL组件
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      //错误处理
      ...
      //构建参数替换的辅助数组parameterHandlers
      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);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
        
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      //错误处理
     ...
      return new ServiceMethod<>(this);
    }
  • 用户调用enqueue方法发起异步请求

ExecutorCallbackCall.enqueue()

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");
      //调用OkhttpCall的enqueue方法,Executor执行响应结果
      delegate.enqueue(new Callback<T>() {
        
        }
      });
    }

OkHttpCall. enqueue

 @Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
          ...
          //这里创建请求报文获得realCall
          call = rawCall = createRawCall();
           ...
    }
    //realCall发起异步请求
    call.enqueue(new okhttp3.Callback() {
           ...
          //转换响应报文
          response = parseResponse(rawResponse);
          ...
   
    });
  }

createRawCall

  private okhttp3.Call createRawCall() throws IOException {
    //创建request报文
    Request request = serviceMethod.toRequest(args);
    //获得okhttp.realCall
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

serviceMethod.toRequest(args)

  Request toRequest(@Nullable Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);
    ...
    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
    //根据先前的parameterHandlers进行参数转换
    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }
    //创建request报文
    return requestBuilder.build();
  }

parseResponse

 Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    //异常处理,200-299成功状态码,204和205没有响应body
   ...
      //serviceMethod.toResponse用户转换器转换
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);

  }

总结

通过梳理大体了解的Retrofit的整体结构和流程,当然还有很多的细节没有讨论,需要时可以查看相应的源码。
Retrofit源码本身并不复杂,但是Retrofit的架构设计,解耦所透露的架构经验,思想,规范等是非常值得我们学习和参照设计的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 适配器模式上一篇文章我们已经分析了Retrofit解析注解封装进ServiceMethod的流程,读者在这里要记住...
    andcoder阅读 643评论 0 2
  • 最近非常流行 Retrofit+RxJava+OkHttp 这一整套的网络请求和异步操作的开源框架,从 Jake ...
    慌不要慌阅读 1,966评论 1 7
  • Retrofit这个开源库出来也有一定年头了,记得之前还是在V1.0的版本的时候,之前在三月份也写过一个Retro...
    lovejjfg阅读 1,427评论 0 5
  • 一、什么是Retrofit A type-safe HTTP client for Android and Jav...
    andcoder阅读 742评论 2 3
  • 好的开场白是成功的一半,很多演讲高手都说,如果没有一个好的开头,想在整个演说过程中做到轻松、巧妙地与听众交流思想交...
    苗轩鸣阅读 444评论 0 2