Retrofit2.5如何发送请求和处理响应?

Retrofit对请求方法的解析

Retrofit对我们在接口类中定义的方法是如何转换成了请求,又如何处理响应。这一切都在它的loadServiceMethod方法中

代码基于Retrofit2.5.0

  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);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

主要是调用ServiceMethod.parseAnnotations

  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);//这里就是对请求的解析,也就是我们定义的接口方法

    Type returnType = method.getGenericReturnType();//获取返回的类型
    //省略无关代码

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

RequestFactory.parseAnnotations这个方法就是对我们定义的接口方法的解析,在里面解析注解和使用反射得到了关于请求的所有信息。

响应的处理

在完成了对请求的处理后构建了RequestFactory类,这个类里面包含了请求的所有信息:

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

  private final Method method;
  private final HttpUrl baseUrl;
  final String httpMethod;
  private final @Nullable String relativeUrl;
  private final @Nullable Headers headers;
  private final @Nullable MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;

接下来继续来看ServiceMethod的parseAnnotations剩下的语句

ServiceMethod.parseAnnotations

  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //省略无关代码

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);//对响应的处理
  }

HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);//创建请求适配器
    Type responseType = callAdapter.responseType();
    //省略无关代码
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);//创建响应数据转换器(Gson)

    okhttp3.Call.Factory callFactory = retrofit.callFactory;//Okhttp请求客户端
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

创建请求适配器CallAdapter

首先进入第一行
HttpServiceMethod.createCallAdapter

  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method) {
    Type returnType = method.getGenericReturnType();//获取返回的类型
    Annotation[] annotations = method.getAnnotations();//获取注解
    try {
      //noinspection unchecked
      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

  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
  
    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
      //空判断
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
  }

这里面是一个循环获取请求适配器工厂数组callAdapterFactories,在retrofit创建的时候,我们可以知道往这个数组里面加的是Android平台默认的ExecutorCallAdapterFactory

public Retrofit build() {
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));   
}
static class Android extends Platform {
    @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
        @Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      //这里可以看到返回的类
      ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
      return Build.VERSION.SDK_INT >= 24
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
    }    
}

在刚才的循环里,调用了它的get方法,实际就是调用

ExecutorCallAdapterFactory.get

  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);//根据返回类型获取泛型里面的想要获取的响应类型
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

我们定义的返回类型一般是泛型的形式,如Call<Response>或者Observable<Response>,所以Utils.getCallResponseType就是取出泛型里面的类型。最后将得到的类型传入新建的CallAdapter

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

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };

自此就完成了CallAdapter的创建,这里记住它的adapt方法,里面是返回的ExecutorCallbackCall,这个后面会调用,再来继续看。

HttpServiceMethod的parseAnnotations第一行代码到此就完了,继续往下执行:

创建响应数据转换器(如Gson)和请求客户端

HttpServiceMethod.parseAnnotations

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType();//获取具体的响应类型
    //省略无关代码
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

注意这里传给responseConverter的responseType是我们刚才获取Call泛型里面的具体类型,也就是我们想要拿到的实体类类型。

这个过程跟刚才创建CallAdapter的过程很像,就连方法名都很像,所以来看看createResponseConverter方法:

HttpServiceMethod.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);
    }
  }

通过method的getAnnotations拿到注解列表,然后跟返回类型传入responseBodyConverter方法:

retrofit.responseBodyConverter

  public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }
  public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }

这个过程简直跟刚才创建CallAdapter的过程一模一样,也是循环从converterFactories取出Converter,根据之前Retrofit的创建时我们传入的是GsonConverterFactory,所以是调用的它的responseBodyConverter方法:

GsonConverterFactory.responseBodyConverter

  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

这里的代码就很面熟了,通过TypeToken获取类型,之后返回一个Gson解析器,它的convert就是调用Gson进行泛型的解析。

GsonResponseBodyConverter

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      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();
    }
  }
}

到这里就完成了响应字符串的解析器的创建,接下来会执行

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);

创建okhttp请求的客户端,这里命名为callFactory,在Retrofit创建的时候我们传入的okhttpClient就是赋值给了callFactory,最后将创建好的对象传入HttpServiceMethod返回。

到此为止就执行完了HttpServiceMethod的parseAnnotations方法,在这个方法里面,创建了几个重要的东西

  • 对请求和响应做具体处理的CallAdapter类,具体为ExecutorCallAdapterFactory,这里要注意它的adapt方法返回ExecutorCallbackCall
  • 响应数据解析工厂Converter,具体为GsonResponseBodyConverter
  • okhttp请求客户端

发送请求

终于到了这一步了,在做好了所有的准备工作之后,最终Retrofit怎么来发送请求呢,首先一步步回到最开始的地方:
在HttpServiceMethod.parseAnnotations方法是在ServiceMethod的parseAnnotations调用的

ServiceMethod.parseAnnotations

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    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.");
    }

    //在这里调用并返回
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract T invoke(Object[] args);
}

然后ServiceMethod.parseAnnotations方法是在Retrofit的loadServiceMethod调用的

然后loadServiceMethod是在Retrofit的create方法里面创建动态代理的invoke调用的

Retrofit.create

  public <T> T create(final Class<T> service) {
    //省略无关代码
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          //省略无关代码

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            //省略无关代码
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

可以看到,在loadServiceMethod之后调用了invoke方法,也就是ServiceMethod的invoke方法,点进去之后发现它是个ServiceMethod是个抽象类,它的invoke需要实现类来重写:

abstract class ServiceMethod<T> {
    abstract T invoke(Object[] args);
}

ServiceMethod类只有一个实现类,也就是我们刚才看到过的HttpServiceMethod,所以实际上调用的是它的invoke方法:

HttpServiceMethod.invoke

  @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }

在这里只有一行代码,实际上是调用callAdapter.adapt,那这个callAdapter是什么呢?刚才我们已经知道它是ExecutorCallAdapterFactory创建的,然后在创建的callAdapter的adapt方法返回ExecutorCallbackCall类,所以来看看这个类:

ExecutorCallbackCall是ExecutorCallAdapterFactory的静态内部类

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) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              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(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }

在这个类里面,我们就看到了很多很熟悉的方法,enqueue方法发送请求,实际的请求和处理就是在这里面,但是还有疑惑就是具体的处理我们还是没看到,callbackExecutordelegate这两个熟悉才是关键所在:

callbackExecutor

这个是在ExecutorCallAdapterFactory的构造方法中传入的,它的构造方法又是在Platform的defaultCallAdapterFactories方法中调用的,看到Platform,自然可以想到它的Android平台类,所以这个callbackExecutor实际上是MainThreadExecutor

    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    
    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }    

其实代码很简单,使用了我们最常用的Handler,让代码在主线程中执行,也就是我们通常做的在子线程请求网络,主线程中更新UI。

delegate

delegate实际是在HttpServiceMethod的invoke方法里传入:

  @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }

实际上是OkHttpCall这个类,这个类里面就是发送请求和处理响应的具体处理,代码很多,我们只看看构造方法和enqueue

  OkHttpCall(RequestFactory requestFactory, Object[] args,
      okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {
    this.requestFactory = requestFactory;//请求工厂,里面包含了请求的所有信息
    this.args = args;//参数
    this.callFactory = callFactory;//请求客户端,okhttp
    this.responseConverter = responseConverter;//响应的json解析器(Gson)
  }

OkHttpCall.enqueue

  @Override public void enqueue(final Callback<T> callback) {
    checkNotNull(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 {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

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

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

    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) {
          t.printStackTrace();
        }
      }

      @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) {
          t.printStackTrace();
        }
      }
    });
  }

代码其实很简单,就是使用okhttp请求,然后在响应方法onResponse做相应的解析和处理,最后完成网络请求。

总结

Retrofit对响应的解析大概可分为

  1. 创建处理适配器CallAdapter,具体实现类为ExecutorCallbackCall,在这里面进行发送请求和处理响应等相关的操作,最终是调用okhttp进行网络请求
  2. 创建响应数据转换器Converter,具体实现类为GsonResponseBodyConverter,用于对返回json数据的解析,这个是我们自己传入的Gson解析工厂,Retrofit也支持其他的第三方解析库
  3. 发送请求,具体的操作类是OkHttpCall来发送请求和处理响应,MainThreadExecutor来做回调的处理,在主线程中处理已经转化好的实体类。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • Retrofit2 源码解析 注意: 本文是对源码的一个跟踪,会对每一行代码有具体的阐述,但是不会介绍 Retro...
    Yjnull阅读 2,883评论 3 17
  • 适配器模式上一篇文章我们已经分析了Retrofit解析注解封装进ServiceMethod的流程,读者在这里要记住...
    andcoder阅读 644评论 0 2
  • 一,前言 Retrofit其实是将OKhttp封装起来,和volley一样。那解析Retrofit其实就是解析它如...
    求闲居士阅读 1,320评论 2 5
  • Retrofit这个开源库出来也有一定年头了,记得之前还是在V1.0的版本的时候,之前在三月份也写过一个Retro...
    lovejjfg阅读 1,429评论 0 5
  • 女儿最近脸上有白色的斑点,昨天带她去医院检查。因为知道如果一开始就告诉她我们去医院,她肯定会排斥和不愿意。一开...
    爱自己2023阅读 183评论 0 0