Retrofit源码学习

前言

学习Retrofit的源码已经有一段时间了,最近又翻了一遍,然后总结了一下。它里面用到了很多个设计模式,有工厂模式、代理模式、适配器模式等。

Create方法

mRetorfit.create(Service.clss)

create方法的返回语句如下:

    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 {
            ......
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });

使用了动态代理,将每次要执行的Service方法做拦截,然后交给里面的三个语句去执行。

loadServiceMethod(method)

  ServiceMethod<?, ?> loadServiceMethod(Method method) {
  //从缓存中获取ServiceMethod对象
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
      //构建ServiceMethod对象,并缓存起来
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

此方法用于获取ServiceMethod对象,首先从缓存中获取,如果找不到则构建一个并且缓存起来。保证每个Service中定义的方法只创建对应一个ServiceMethod对象。

ServiceMethod.Builder

Builder代码比较多,它里面初始化了几个重要的对象:callAdapter、responseConverter、parameterHandlers,并且解析注解,然将这些对象都保存起来,用于创建ServiceMethod对象时进行初始化。

ServiceMethod

构造函数如下:

  ServiceMethod(Builder<R, 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;
  }

其中几个比较重要的成员:

  • callFactory :OkHttp.Call.Factory对象,默认是OkHttpClient,用于构建Http请求,创建Call对象。
  • callAdapter:将Call< R >转换成T的一个策略,可以直接返回Call< R >,由创建Retrofit时传进addCallAdapterFactoryr方法的Factory创建。
    • RxJava
    • Java8
    • Android
    • Guava
  • responseConverter :数据转换器,将服务端返回的数据转换成我们想要的数据类型。由创建Retrofit时传进addConverterFactory方法的Factory创建,用于将获取的数据转换成我们需要的格式。

OkHttpCall

OkHttpCall是对OkHttp进行包装的一个类,创建的时候会初始化serviceMethod和参数数组args。同样里面有enqueue方法和execute方法。

CallAdapter

它的创建是在ServiceMethod中的createCallAdapter方法中,然后调用以下的语句:

retrofit.callAdapter(returnType, annotations)

也就是根据返回类型和注解,在Retrofit中进行创建:

public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

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

首先进行校验,然后通过工厂类进行获取并返回。结合RxJava,所以使用的是RxJava2CallAdapterFactory ,所以这里获取到的是一个RxJava2CallAdapter对象。

RxJava2CallAdapter#adapt()

@Override public Object adapt(Call<R> call) {
//根据是否同步,创建对应的Observable对象
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }

根据是否同步创建出对应的Observable对象,然后进行返回。
当我们使用结合RxJava时,会在方法返回类型定位Observable,然后调用subscribe传入一个Observer对象,也就是开始订阅;在subscribe方法中,会调用subscribeActual方法并且传入Observer对象,而CallEnqueueObservable和CallExecuteObservable都实现了subscribeActual方法。

CallEnqueueObservable#subscribeActual

@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
    // 由于每个Call只能发起一次请求,所以要克隆出新的Call对象
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    //执行异步请求
    call.enqueue(callback);
  }

其中的originalCall也就是OkHttpCall,它的enqueue方法里同步语句中有两句重要的代码:

call = rawCall = createRawCall();//1
call.enqueue(...)//2
response = parseResponse(rawResponse);//3
  1. 创建okhttp3.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对象,然后通过最开始的callFactory创建Call并返回。

2 . Call发起网络请求,然后将请求结果进行解析
3 . 解析过程通过返回码做进一步的判断,如果响应正常,则会调用serviceMethod.toResponse(catchingBody):

R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

toResponse方法调用了Converter对象的convert,对返回数据转换成我们想要的数据格式,比如我们最开始进去的是GsonConverterFactory.create(),则会将返回数据转换成Json格式并返回,除此之外还有XML解析器等。Converter的创建也是根据我们设置的Converter工厂在Retrofit中创建的。

到此基本过了一遍从创建、获取数据、转换数据的流程。

总结

  1. 创建Retrofit,
    1.1 创建的时候初始化ConverterFactory,它用于将某些数据格式转换为目标类型
    1.2 创建CallAdapterFactory,用于将Call转换成目标类型,也就是我们在定义方法的返回类型,默认返回ExecutorCallbackCall
    1.3 创建Executor,表示在哪个平台执行,默认是MainThreadExecutor,它会将响应结果的回调发送到主线程中
    1.4 创建CallFactory,默认是OkHttpClient,创建OkHttp中的Call

  2. 执行方法:每执行一个接口定义的方法都会通过动态代理的方式
    2.1 初始化ServiceMethod,首先会从缓存中获取,如果不存在则根据Method创建一个并缓存起来
    2.2 创建OkHttpCall
    2.3 调用CallAdapter的adapt方法,默认返回的是一个ExecutorCallbackCall,并将OkHttpCall传递进去
    2.4 返回代理创建的Call对象

  3. 发起网络请求
    3.1 enqueue方法会让delegate执行它的enqueue方法,这个delegate是OkHttpCall,在它里面发起网络请求
    3.2 OkHttpCall的enqueue方法里面会通过ServiceMethod根据参数和方法注解创建Request,然后通过OkHttpClient创建一个OkHttp的Call对象,然后发起网络请求(getResponseWithInterceptorChain方法)
    3.3 获取到响应后,进行解析,如果成功,则通过ServiceMethod进行转换,底层是使用ResponseConverter将响应结果转换成我们的目标类型
    3.4 将目标类型实例封装到Response中,并回调到对应平台中(MainThreadExecutor:将回调发送到主线程中执行)

你可能感兴趣的:(Android)