美文网首页Android精选
Retrofit源码解析

Retrofit源码解析

作者: 左大人 | 来源:发表于2018-11-13 18:36 被阅读135次

    序言

    做Android开发的小伙伴都知道,现在最流行的网络框架就是RxJava+Retrofi+OkHttp。今天我们就一起来学习一下Retrofit内部如何实现。

    文章将会从下面几个点展开介绍:

    一、 如何使用Retrofit

    二、 Retrofit源码解析

    1. 构建Retrofit对象
    2. 创建Service实例
    3. 执行一次请求的具体流程

    三、总结

    如何使用Retrofit

    首先,介绍如何在我们的项目中使用Retrofit。
    本文基于Retrofit2.0,并且结合RxJava的使用进行分析,但不涉及RxJava原理分析。

    1. 在工程Module的build.gradle中添加Retrofit依赖库
    api "com.squareup.retrofit2:retrofit:2.0.0"
    api "com.squareup.retrofit2:adapter-rxjava:2.0.0"
    api "com.squareup.retrofit2:converter-jackson:2.0.0"
    
    1. 定义一个提供服务的接口Service
    public interface DeviceService {
        /**
         * 上传用户设备信息
         *
         * @param deviceInfo 设备信息
         */
        @POST(URLConstants.UPLOAD_DEVICE_INFO)
        @FormUrlEncoded
        Observable<BaseResponse<Object>> uploadDeviceInfo(@FieldMap Map<String, String> deviceInfo);
    }
    
    1. 定义Retrofit
    public enum DeviceRetrofit {
        SINGLETON;
    
        private static final String TAG = "DeviceRetrofit";
        private DeviceService mService;
    
        DeviceRetrofit() {
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(Config.HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
                    .retryOnConnectionFailure(true)
                    .addInterceptor(new DeviceInterceptor())
                    .addInterceptor(OkHttpUtils.getHttpInterceptor(TAG))
                    .build();
    
            Retrofit retrofit = new Retrofit.Builder()
                    .client(okHttpClient)
                    .baseUrl(Config.DEVICE_HOST)
                    .addConverterFactory(JacksonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .build();
            mService = retrofit.create(DeviceService.class);
        }
    
        public DeviceService getService() {
            return mService;
        }
    }
    

    DeviceRetrofit是一个单例类,通过枚举实现单例模式,在构造方法中构建Retrofit对象,用Retrofit初始化service对象,并且对外提供了service对象。

    1. 调用service方法发送请求
    /**
     * 数据层DeviceModel
     */
    public class DeviceModel extends BaseModel {
        /**
         * 上传用户设备信息
         */
        public Observable uploadDeviceInfo(UserDevBody userDevBody) {
            return DeviceRetrofit.SINGLETON.getService().uploadDeviceInfo(DeviceInfoHelper.transform(userDevBody))
                    .compose(RxUtils.defaultResponse())
                    .subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io());
        }
    }
    

    到这里就已经返回了一个经过基础转换的Observable,之后我们只需要对这个Observable进行处理,得到我们想要的数据即可。

    Retrofit源码解析

    可以说整个使用过程并不复杂,在我们用这么少的代码就能够发送一个网络请求的背后,是Retrofit帮我们做了大量的工作,包括解析参数,组装请求,对数据进行转换和适配...
    下面我们通过源码来分析Retrofit:

    1. 构建Retrofit对象

    我们先看一下构建Retrofit的代码:

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
             .connectTimeout(Config.HTTP_TIMEOUT, TimeUnit.MILLISECONDS)
             .retryOnConnectionFailure(true)
             .addInterceptor(new DeviceInterceptor())
             .addInterceptor(OkHttpUtils.getHttpInterceptor(TAG))
             .build();
        
    Retrofit retrofit = new Retrofit.Builder()
            .client(okHttpClient)
            .baseUrl(Config.DEVICE_HOST)
            .addConverterFactory(JacksonConverterFactory.create(mapper))
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
    

    Retrofit是通过Builder模式来构建对象,我们先看一下Retrofit的定义:

    public final class Retrofit {
        private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
        
        private final okhttp3.Call.Factory callFactory;
        private final HttpUrl baseUrl;
        private final List<Converter.Factory> converterFactories;
        private final List<CallAdapter.Factory> adapterFactories;
        private final Executor callbackExecutor;
        private final boolean validateEagerly;
        
        Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
            List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
            Executor callbackExecutor, boolean validateEagerly) {
            this.callFactory = callFactory;
            this.baseUrl = baseUrl;
            this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
            this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
            this.callbackExecutor = callbackExecutor;
            this.validateEagerly = validateEagerly;
        }
    
        //省略其他代码
    }
    

    Retrofit包含一些重要的成员:

    • serviceMethodCache:是一个LinkedHashMap<Method, ServiceMethod>,声明时直接初始化,用来缓存ServiceMethod,避免重复创建,可以提高性能
    • callFactory:请求工厂,主要要来创建请求(Call)
    • baseUrl:服务器域名,即服务器host
    • converterFactories:数据解析工厂,可以创建Converter,主要用来解析Response,可以有多个,但只有一个会进行真正的解析操作
    • adapterFactories:数据适配工厂,可以创建适配器,主要作用是把Response中的数据转换为某种数据源类型,比如我们示例中把Response转换为rxjava.Observable
    • callbackExecutor:请求线程池
    • validateEagerly:是否设置为饥饿模式,如果设置为饥饿模式,会提前初始化ServiceMethod,后面分析中会做介绍

    分析完Retrofit中的成员变量之后,我们来看一下Builder如何初始化这些成员变量,先看一下Builder的构造方法:

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

    需要传一个Platform对象:

    class Platform {
        private static final Platform PLATFORM = findPlatform();
        
        static Platform get() {
          return PLATFORM;
        }
        
        private static Platform findPlatform() {
          try {
            Class.forName("android.os.Build");
            if (Build.VERSION.SDK_INT != 0) {
              return new Android();
            }
          } catch (ClassNotFoundException ignored) {
          }
          try {
            Class.forName("java.util.Optional");
            return new Java8();
          } catch (ClassNotFoundException ignored) {
          }
          try {
            Class.forName("org.robovm.apple.foundation.NSObject");
            return new IOS();
          } catch (ClassNotFoundException ignored) {
          }
          return new Platform();
        }
    }
    

    Platform.get方法返回PLATFORM成员,而这个成员通过findPlatform方法初始化,我们使用的是Android平台,所以直接返回一个Android对象,接下来看一下Platform的静态内部类Android的定义:

    static class Android extends Platform {
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
        
        @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
          return new ExecutorCallAdapterFactory(callbackExecutor);
        }
        
        static class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
        
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
    }
    

    Platform的作用是帮助初始化Retrofit。而不同的平台会使用不同的对象去初始化Retrofit,我们只关心Android平台。
    接下来看一下Builder的build方法:

    public Retrofit build() {
        if (baseUrl == null) {
          throw new IllegalStateException("Base URL required.");
        }
        
        okhttp3.Call.Factory callFactory = this.callFactory;
        if (callFactory == null) {
          callFactory = new OkHttpClient();
        }
        
        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
          callbackExecutor = platform.defaultCallbackExecutor();
        }
        
        // Make a defensive copy of the adapters and add the default Call adapter.
        List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
        adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
        
        // Make a defensive copy of the converters.
        List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
        
        return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
            callbackExecutor, validateEagerly);
    }
    

    build方法会初始化Retrofit大部分成员:

    • baseUrl:我们通过builder对象手动设置,例子中的是Config.DEVICE_HOST,只需要知道,这是一个host就可以
    • callFactory:我们通过builder设置的OkHttpClient对象
    • callExecutor:platform.defaultCallbackExecutor,Android平台是MainThreadExecutor类型,它是主线程线程池,所有的请求都是在主线程发送一个消息,在异步线程中执行请求,最后在主线程中处理回调
    • adapterFactories:添加一个ExecutorCallAdapterFactory,而我们又通过bulder设置了一个RxJavaCallAdapterFactory,所以adapterFactories中有两个元素,最后会使用到RxJavaCallAdapterFactory
    • converterFactories:通过builder设置,是JacksonConverterFactory类型
    • validateEagerly:默认为false

    可以看到,在Retrofit.Builder.build方法中,初始化了Retrofit所有的成员。

    至此,构建Retrofit对象的过程介绍完毕。总结一下,就是创建了一个Retrofit对象,并且初始化了它的所有成员变量

    2. 创建Service实例

    Retrofit对象初始化之后,就会初始化Service对象,代码如下:

    mService = retrofit.create(DeviceService.class);
    

    Retrofit调用create方法初始化Service对象:

    public <T> T create(final Class<T> service) {
      Utils.validateServiceInterface(service);
      if (validateEagerly) {
        eagerlyValidateMethods(service);
      }
      return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
          new InvocationHandler() {
            private final Platform platform = Platform.get();
    
            @Override public Object invoke(Object proxy, Method method, Object... args)
                throws Throwable {
              // If the method is a method from Object then defer to normal invocation.
              if (method.getDeclaringClass() == Object.class) {
                return method.invoke(this, args);
              }
              if (platform.isDefaultMethod(method)) {
                return platform.invokeDefaultMethod(method, service, proxy, args);
              }
              ServiceMethod serviceMethod = loadServiceMethod(method);
              OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
              return serviceMethod.callAdapter.adapt(okHttpCall);
            }
          });
    }
    

    这段代码中,我们着重看两个地方:

    饥饿模式

    如果validateEagerly为true,就会调用eagerlyValidateMethod方法:

    private void eagerlyValidateMethods(Class<?> service) {
      Platform platform = Platform.get();
      for (Method method : service.getDeclaredMethods()) {
        if (!platform.isDefaultMethod(method)) {
          loadServiceMethod(method);
        }
      }
    }
    

    这个方法通过反射,获取Service中定义的所有方法,并且遍历,对每个方法做loadServiceMethod处理,而loadServiceMethod就是为一个方法创建一个ServiceMethod对象,可见validateEagerly的作用就是提前初始化Service方法对应的ServiceMethod
    至于ServiceMethod是什么,我们后面分析。

    动态代理

    使用动态代理模式构建Service实例,了解动态代理的同学知道,动态代理可以自动帮我们生成代理类,我们调用代理类的方法,最后都会调用到InvocationHandler的invoke方法,它的好处在于可以对所有方法做统一处理。
    而Retrofit正是需要对Service的方法做统一处理:

    • 判断方法是否属于Object,如果是的,直接调用方法
    • 判断方法是否为platform的默认方法,Android平台都返回false
    • 方法属于Service,则会执行以下三句代码(因为是Android平台,所以肯定会走到这里):
    ServiceMethod serviceMethod = loadServiceMethod(method);
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    return serviceMethod.callAdapter.adapt(okHttpCall);
    

    到这里,创建Service实例完毕。总结一下,Retrofit通过动态代理的方式初始化一个实现了Service的代理类

    3. 执行一次请求的具体流程

    Retrofit和Service初始化之后,我们尝试进行一次请求,即调用一次Service的方法,它的流程是什么样的呢?

    这就要回到上面介绍的动态代理,每次调用service方法最后都会执行InvocationHandler.invoke方法,这个方法对所有的请求做统一处理,即上面提到的三句代码,下面逐句分析:

    第一句:构建一个ServiceMethod对象
    ServiceMethod serviceMethod = loadServiceMethod(method);
    

    在饥饿模式中也提到了loadServiceMethod方法的,这个方法会接收method作为参数,返回一个ServiceMethod对象:

    ServiceMethod loadServiceMethod(Method method) {
      ServiceMethod result;
      synchronized (serviceMethodCache) {
        result = serviceMethodCache.get(method);
        if (result == null) {
          result = new ServiceMethod.Builder(this, method).build();
          serviceMethodCache.put(method, result);
        }
      }
      return result;
    }
    

    先从serviceMethodCache找是否存在该方法对应的ServiceMethod,如果没有,创建一个ServiceMethod对象,并且把<method, MethodService>保存到serviceMethodCache中,下次调该方法就可以直接从serviceMethodCache中获取ServiceMethod,而不用重复创建,提高性能。
    ServiceMethod也采用Builder模式来创建对象,我们先看一下ServiceMethod的定义:

    /** Adapts an invocation of an interface method into an HTTP call. */
    final class ServiceMethod<T> {
      // Upper and lower characters, digits, underscores, and hyphens, starting with a character.
      static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
      static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
      static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
    
      final okhttp3.Call.Factory callFactory;
      final CallAdapter<?> callAdapter;
    
      private final HttpUrl baseUrl;
      private final Converter<ResponseBody, T> responseConverter;
      private final String httpMethod;
      private final String relativeUrl;
      private final Headers headers;
      private final MediaType contentType;
      private final boolean hasBody;
      private final boolean isFormEncoded;
      private final boolean isMultipart;
      private final ParameterHandler<?>[] parameterHandlers;
    
      ServiceMethod(Builder<T> builder) {
        this.callFactory = builder.retrofit.callFactory();
        this.callAdapter = builder.callAdapter;
        this.baseUrl = builder.retrofit.baseUrl();
        this.responseConverter = builder.responseConverter;
        this.httpMethod = builder.httpMethod;
        this.relativeUrl = builder.relativeUrl;
        this.headers = builder.headers;
        this.contentType = builder.contentType;
        this.hasBody = builder.hasBody;
        this.isFormEncoded = builder.isFormEncoded;
        this.isMultipart = builder.isMultipart;
        this.parameterHandlers = builder.parameterHandlers;
      }
    }
    

    ServiceMethod的类注释介绍了它的作用,就是把一次接口的方法调用转换成一个Http请求。它也包含了很多成员变量,都是与Http请求有关的一些参数,在Builder.build方法中会初始化这些参数:

    public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }
     
    public ServiceMethod build() {
      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?");
      }
      responseConverter = createResponseConverter();
    
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
    
      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }
    
      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }
    
      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);
      }
    
      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }
    
      return new ServiceMethod<>(this);
    }
    

    下面列举一下ServiceMethod的成员变量及构造过程中初始化情况:

    • callFactory:跟Retrofit.callFactory一样,即OkHttpClient
    • callAdapter:根据方法的返回类型,从Retrofit的两个callFactory中匹配得到RxJavaCallAdapterFactory,具体匹配过程同学们可以自行跟踪代码。通过RxJavaCallAdapterFactory创建该方法对应的RxJavaCallAdapterFactory.SimpleCallAdapter
    • baseUrl:同Retrofit的baseUrl一致
    • responseConverter:通过Retrofit的converterFactory创建的JacksonResponseBodyConverter对象
    • httpMethod:从方法注解中解析得到,即GETPOST等Http请求类型
    • relativeUrl:请求地址,一般是从请求类型注解中解析得到,如@GET("order/query/101")对应的relativeUrl是order/query/101
    • header:请求头信息,从方法注解@Headers中解析得到
    • contentType:请求的数据类型,从@Headers中解析得到
    • hasBody:请求是否有内容部分(body),DELETE/GET/HEAD/OPTIONS类型的请求没有,POST/PATCH/PUT类型请求有
    • isFormEncoded:从方法上是否有@FormUrlEncoded判断,不能与@Multipart同时存在,前提条件是hasBody=true
    • isMultipart:从方法上是否有@Multipart判断,不能与@FormUrlEncoded同时存在,前提条件是hasBody=true
    • parameterHandlers:数组类型,从方法的参数注解解析得到,数量与方法参数数量一直,作用是参数信息设置到Http请求构造器RequestBuilder中

    可以看到,loadServiceMethod方法就是根据method构建一个ServiceMethod对象。在构建的过程中,解析方法上的注解和参数注解,初始化ServiceMethod的所有成员变量。
    具体的解析过程不详细介绍,代码比较多,对着可以自己参照源码学习。

    第二句:创建OkHttpCall
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    

    OkHttpCall是Call的实现类,定义如下:

    final class OkHttpCall<T> implements Call<T> {
      private final ServiceMethod<T> serviceMethod;
      private final Object[] args;
    
      private volatile boolean canceled;
    
      // All guarded by this.
      private okhttp3.Call rawCall;
      private Throwable creationFailure; // Either a RuntimeException or IOException.
      private boolean executed;
    
      OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
        this.serviceMethod = serviceMethod;
        this.args = args;
      }
    
      //省略其他代码
    }
    

    从定义中可知,OkHttpCall构造方法接收ServiceMethod和参数数组,并且还有还有一个成员rawCall(okhttp3.Call类型),它的作用是执行请求并且管理请求的状态和处理请求回调。

    第三句:执行请求
    return serviceMethod.callAdapter.adapt(okHttpCall);
    

    调用了callAdapter.adapt方法,而serviceMethod.callAdapter是RxJavaCallAdapterFactory.SimpleCallAdapter对象,所以我们直接看SimpleCallAdapter的adapt方法:

    static final class SimpleCallAdapter implements CallAdapter<Observable<?>> {
      private final Type responseType;
      private final Scheduler scheduler;
    
      SimpleCallAdapter(Type responseType, Scheduler scheduler) {
        this.responseType = responseType;
        this.scheduler = scheduler;
      }
    
      @Override public Type responseType() {
        return responseType;
      }
    
      @Override public <R> Observable<R> adapt(Call<R> call) {
        Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) //
            .flatMap(new Func1<Response<R>, Observable<R>>() {
              @Override public Observable<R> call(Response<R> response) {
                if (response.isSuccessful()) {
                  return Observable.just(response.body());
                }
                return Observable.error(new HttpException(response));
              }
            });
        if (scheduler != null) {
          return observable.subscribeOn(scheduler);
        }
        return observable;
      }
    }
    

    用CallOnSubscribe构建了一个Observable对象,看一下CallOnSubscribe的实现:

    static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> {
      private final Call<T> originalCall;
    
      CallOnSubscribe(Call<T> originalCall) {
        this.originalCall = originalCall;
      }
    
      @Override public void call(final Subscriber<? super Response<T>> subscriber) {
        // Since Call is a one-shot type, clone it for each new subscriber.
        final Call<T> call = originalCall.clone();
    
        // Attempt to cancel the call if it is still in-flight on unsubscription.
        subscriber.add(Subscriptions.create(new Action0() {
          @Override public void call() {
            call.cancel();
          }
        }));
    
        try {
          Response<T> response = call.execute();
          if (!subscriber.isUnsubscribed()) {
            subscriber.onNext(response);
          }
        } catch (Throwable t) {
          Exceptions.throwIfFatal(t);
          if (!subscriber.isUnsubscribed()) {
            subscriber.onError(t);
          }
          return;
        }
    
        if (!subscriber.isUnsubscribed()) {
          subscriber.onCompleted();
        }
      }
    }
    

    CallOnSubscribe实现了rxjava中的Observable.OnSubscribe接口,当Observable对象调用subscribe方法的时候,就会执行OnSubscribe的call方法(可参照RxJava源码)。
    call方法中着重关注call.execute()这句代码,这里的call是上面提到的的OkHttpCall对象,所以看OkHttpCall的execute方法:

    @Override public Response<T> execute() throws IOException {
      okhttp3.Call call;
    
      synchronized (this) {
        if (executed) throw new IllegalStateException("Already executed.");
        executed = true;
    
        if (creationFailure != null) {
          if (creationFailure instanceof IOException) {
            throw (IOException) creationFailure;
          } else {
            throw (RuntimeException) creationFailure;
          }
        }
    
        call = rawCall;
        if (call == null) {
          try {
            call = rawCall = createRawCall();
          } catch (IOException | RuntimeException e) {
            creationFailure = e;
            throw e;
          }
        }
      }
    
      if (canceled) {
        call.cancel();
      }
    
      return parseResponse(call.execute());
    }
    

    主要逻辑:检查call是否为空,如果为空,则调用createRawCall方法创建call对象(okhttp3.Call),然后调用call.execute()方法,并且用convert把响应结果转换为Response对象。
    这段代码我们关注两个点:a. 初始化call对象 b. 调用call.execute方法执行请求。下面一次介绍:
    a. 初始化call对象

    private okhttp3.Call createRawCall() throws IOException {
      Request request = serviceMethod.toRequest(args);
      okhttp3.Call call = serviceMethod.callFactory.newCall(request);
      if (call == null) {
        throw new NullPointerException("Call.Factory returned null.");
      }
      return call;
    }
    

    先把ServiceMethod转化为Request对象,然后用Request构建一个okhttp3.Call对象,serviceMethod.callFactory是OkHttpClient对象,跟踪到OkHttpClient.newCall方法:

    @Override public Call newCall(Request request) {
      return RealCall.newRealCall(this, request, false /* for web socket */);
    }
    

    这里创建了一个RealCall对象,它是OkHttp中Call的实现类,是真正的请求类。

    b. 调用call.execute方法执行请求
    真正的请求类是RawCall,所以我们直接看RawCall的execute方法:

    @Override public Response execute() throws IOException {
        synchronized (this) {
        if (executed) throw new IllegalStateException("Already Executed");
        executed = true;
      }
      captureCallStackTrace();
      eventListener.callStart(this);
      try {
        client.dispatcher().executed(this);
        Response result = getResponseWithInterceptorChain();
        if (result == null) throw new IOException("Canceled");
        return result;
      } catch (IOException e) {
        eventListener.callFailed(this, e);
        throw e;
      } finally {
        client.dispatcher().finished(this);
      }
    }
    

    这段代码就涉及到OkHttp的请求机制,这里不做解释,后面会单独出一篇OkHttp的文章。
    总之执行了请求之后,会生成一个okhttp3.Response对象,然后通过OkHttpCall.parseResponse方法把okhttp3.Response转换为retrofit2.Response类型:

    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) {
        return Response.success(null, rawResponse);
      }
    
      ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
      try {
        T body = serviceMethod.toResponse(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;
      }
    }
    

    这里返回的Response交给RxJava处理,最后返回给客户端。到此,一个请求的整个流程就介绍完毕了。

    总结

    文章比较长,不知道各位同学是否看明白。在阅读Retrofit源码的过程中,往往会陷入细节中无法自拔,导致不能对Retrofit整体把握。下面,是我自己梳理的一张Retrofit架构图,包括一次请求执行的流程:


    Retrofit架构流程图.png

    这张图基本概括了上面描述的所有内容,如果各位有什么不懂的欢迎提问。

    相关文章

      网友评论

        本文标题:Retrofit源码解析

        本文链接:https://www.haomeiwen.com/subject/fcnlfqtx.html