Retrofit2.6.1源码分析

1. Retrofit是怎么将回调函数放到主线程的?

看new Retrofit.Builder()的Builder方法
当返回对象为Call,就会使用默认的DefaultCallAdapterFactory
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就是上图中的mainThreadExecutor
        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);
          }
        });
      }
    });
  }

2 retrofit的初始化

2.1 .build()方法干了写什么?

//new Retrofit.Builde().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();
    }
    // 配置回调方法执行器(callbackExecutor)-
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
      callbackExecutor = platform.defaultCallbackExecutor();
    }
 
    //配置网络请求适配器工厂(CallAdapterFactory)
    // Make a defensive copy of the adapters and add the default Call adapter.
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    //CompletableFutureCallAdapterFactory中包含BodyCallAdapter与ResponseCallAdapter(后面会讲到)
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));//注意Android extends Platform
 
    //配置数据转换器工厂:converterFactory
    // Make a defensive copy of the converters.
    List<Converter.Factory> converterFactories = new ArrayList<>(
        1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
 
    // Add the built-in converter factory first. This prevents overriding its behavior but also
    // ensures correct behavior when using converters that consume all types.
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    converterFactories.addAll(platform.defaultConverterFactories());
    //也就是将开始将的handler、defaultCallAdapterFactories与自己添加的CallAdapterFactories、默认的converterFactorie与添加的converterFactories存起来了
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
        unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
  }
}
获取合适的网络请求适配器和数据转换器都是从adapterFactories和converterFactories集合的首位-末位开始遍历,因此集合中的工厂位置越靠前就拥有越高的使用权限

callAdapterFactories里面的callAdapter中包含了执行网络请求的call对象,那么用哪个call去执行网络请求呢?匹配规则

RxJava2CallAdapterFactory:对应返回值Observable
CompletableFutureCallAdapterFactory:如果返回值是Response -> BodyCallAdapter  否则 ResponseCallAdapter
DefaultCallAdapterFactory:  对应返回值为Call,也就是纯retrofit的时候就是它了
 
BuiltInConverters: 返回类型为ResponseBody、Void、Unit
OptionalConverterFactory:  Java8的新特性,Optional.ofNullable(delegate.convert(value)) 避免空指针的
 

2.2 .create()方法中的loadServiceMethod(method).invoke()方法

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();
        private final Object[] emptyArgs = new Object[0];
 
        @Override public @Nullable Object invoke(Object proxy, Method method,
            @Nullable 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)) { //java8 后接口可以写默认方法
            return platform.invokeDefaultMethod(method, service, proxy, args);
          }
          //关键是看这两个方法
          return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
        }
      });
}
先看loadServiceMethod()方法:
ServiceMethod.parseAnnotations(this, method);
 
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
  return new Builder(retrofit, method).build();
}
 
Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  this.methodAnnotations = method.getAnnotations();
  this.parameterTypes = method.getGenericParameterTypes();
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}
//比如这样的一个接口
@POST
fun getLiveRoomUserSig(@Url url: String, @Body body: HashMap<String, String>): Observable<HttpResponse<JBLiveRoomUserSigModel>>
 
    methodAnnotations:POST 也就是方法上的注解
    parameterTypes: String 与 HashMap 也就是方法参数类型
    parameterAnnotationsArray:URL 与 Body 也就是方法的参数注解    
这里我们需要关注下对parameterAnnotationsArray的处理,也就是将我们的参数(比如map)转换成发起网络请求的数据
RequestFactory build() {
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation); //请求方式 POST Get等 的处理
  }
    ...省略部分代码
  //方法上的参数注解处理,比如常用的:@FieldMap @Body
  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
      //需要注意 这里 方法参数注解 与 方法参数类型 是 一一匹配的 不同的是parameterAnnotationsArray是个二维数组,因为一个参数可能有多个注解
    parameterHandlers[p] =
        parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
  }
  private @Nullable ParameterHandler<?> parseParameter(
    int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
  ParameterHandler<?> result = null;
  if (annotations != null) {
    for (Annotation annotation : annotations) {
      ParameterHandler<?> annotationAction =
          parseParameterAnnotation(p, parameterType, annotations, annotation);
 
      if (annotationAction == null) {
        continue;
      }
      //annotations就是上面说的多个注解,这里遍历如果一个参数找到多个Retrofit批注 就抛异常了
      if (result != null) {
        throw parameterError(method, p,
            "Multiple Retrofit annotations found, only one allowed.");
      }
 
      result = annotationAction;
    }
  }
  //紧接着 parseParameterAnnotation 跟进来 这里我们看下常用的
  if (annotation instanceof Body) {
      Converter<?, RequestBody> converter;
      try {
        converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
      } catch (RuntimeException e) {
        // Wide exception range because factories are user code.
        throw parameterError(method, e, p, "Unable to create @Body converter for %s", type);
      }
      gotBody = true;
      return new ParameterHandler.Body<>(method, p, converter);
  }else if (annotation instanceof FieldMap) { //比如 @FormUrlEncoded 的时候 用的这个,
      if (!isFormEncoded) { //可见如果用FieldMap 而不是isFormEncoded的请求方式,就抛异常了
         throw parameterError(method, p,"@FieldMap parameters can only be used with form encoding.");
      }
      Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);
      //默认得到的是 BuiltInConverters.ToStringConverter.INSTANCE
      return new ParameterHandler.FieldMap<>(method, p,
        valueConverter, ((FieldMap) annotation).encoded());
  }

解析完后将每个参数对应的ParameterHandler 都保存到了 parameterHandlers数组中, 再创建RequestFactory对象

也就是说:上面拿到了对请求体的解析,对网络请求前做处理
这里需要注意一个方法:RequestFactory类中有个create()方法,如下图,返回了一个okhttp3.Request对象
在哪里调用?
 
继续看这个方法在哪些地方调用了:
看方法名,很明显这都是在执行网络请求的时候调用的,也是真正执行网络请求的地方。
图中createRawCall()方法三个调用的地方稍后再做具体分析,先看下requestFactory.create()方法干了些啥
okhttp3.Request create(Object[] args) throws IOException {
  @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
  ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
 
  int argumentCount = args.length;//args 就是参数的个数,retrofit代理那块传过来的
  RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,
      headers, contentType, hasBody, isFormEncoded, isMultipart);
 
  if (isKotlinSuspendFunction) {
    // The Continuation is the last parameter and the handlers array contains null at that index.
    argumentCount--;
  }
 
  List<Object> argumentList = new ArrayList<>(argumentCount);
  for (int p = 0; p < argumentCount; p++) {
    argumentList.add(args[p]);
    handlers[p].apply(requestBuilder, args[p]);//遍历parameterHandlers 执行apply方法,为requestBuilder设置请求体
  }
  //再使用requestBuilder构建网络请求的Request对象
  return requestBuilder.get()
      .tag(Invocation.class, new Invocation(method, argumentList))
      .build();
}
继续上面代码的执行流程,就到了下面这个方法,这里就对应了响应数据与网络请求相关的处理:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
  boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
  boolean continuationWantsResponse = false;
  boolean continuationBodyNullable = false;
 
  Annotation[] annotations = method.getAnnotations();
  Type adapterType;
  if (isKotlinSuspendFunction) {
    Type[] parameterTypes = method.getGenericParameterTypes();
    Type responseType = Utils.getParameterLowerBound(0,
        (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
     //ParameterizedType 代表是 参数化类型,简单点说 就是responseType是一个带泛形的类
    if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
      // Unwrap the actual body type from Response<T>.
      responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
      continuationWantsResponse = true;
    } else {
      // TODO figure out if type is nullable or not
      // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
      // Find the entry for method
      // Determine if return type is nullable or not
    }
 
    adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
    annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
  } else {
    adapterType = method.getGenericReturnType();
  }
 //获取相匹配的callAdapter 该callAdapter做了啥? 看下图
  CallAdapter<ResponseT, ReturnT> callAdapter =
      createCallAdapter(retrofit, method, adapterType, annotations);
  // 拿到的responseType是啥? 看下图 当配合RxJava2CallAdapterFactory时,
  // adapterType = Observable<T>   responseType就是我们Observable<T> 的T的类型
  Type responseType = callAdapter.responseType();
  if (responseType == okhttp3.Response.class) {
    throw methodError(method, "'"
        + getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  if (responseType == Response.class) {
    throw methodError(method, "Response must include generic type (e.g., Response<String>)");
  }
  // TODO support Unit for Kotlin?
  if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
    throw methodError(method, "HEAD method must use Void as response type.");
  }
 
  //根据需要的返回类型,来匹配对网络请求成功的json数据的解析类  具体看下图, 最后返回了GsonResponseBodyConverter
  Converter<ResponseBody, ResponseT> responseConverter =
      createResponseConverter(retrofit, method, responseType);
 
  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  //如果返回的类型不是 Suspend 函数 就会返回CallAdapter, 比如当我们使用Rxjava2Adapter时,定义的接口返回的Observable
  if (!isKotlinSuspendFunction) {
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
  } else if (continuationWantsResponse) {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    //如果是 Suspend 函数, 判断方法返回值是不是Response
    return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
        callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
  } else {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    //如果是直接返回实体类的,那么就走到这里来了,注意下面会再次提到这
    return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
        callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
        continuationBodyNullable);
  }
}
上面调用createCallAdapter 打了个断点,可看到createCallAdapter方法里的参数信息如下
再跟下去,
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; //如果我们使用的Rxjava+Retrofit的模式,那么根据上面中的参数,匹配上的CallAdapter就是RxJava2CallAdapter了
  }
}
 
上面返回adapter后,紧接着获取接口请求后的返回类型callAdapter.responseType();
response转换器的创建过程
 
也就是说loadServiceMethod(method)该方法主要是创建并加载ServiceMehod,用于解析网络请求接口参数、网络请求适配器、response数据解析器的工作。
 

2.3. 返回HttpServiceMethod后就调用.invoke()方法,返回OkhttpCall对象

requestFactory 里面包含请求方式、请求Url、请求体
callFactory 为OkhttpClient对象
responseConverter 为我们的json转换,比如GsonConverterFactory
然后将这些数据都放到OkHttpCall中(OkHttpCall<T> implements Call),这里面有两个方法,用来执行网络请求:同步请求execute() 与异步请求 enqueue()
 
这两个方法在哪里开始执行的呢?以RxJava2CallAdapter为例,所以上图中adapter对应的来到
点击去就可以看到在subscribeActual()方法中执行了对应的请求,
点击call.execute(),就来到了OkHttpCall的execute()
public Response<T> execute() throws IOException {
  okhttp3.Call call;
 
  synchronized (this) {
    if (call == null) {
      try {
        call = rawCall = createRawCall(); //这里也就是上文所指的稍后分析的问题了
      } catch (IOException | RuntimeException | Error e) {
      }
    }
  }
  return parseResponse(call.execute()); //解析请求成功后的数据
请求成功后,调用GsonResponseBodyConverter的convert()方法,返回我们需要的实体类,
OkHttpCall - > parseResponse
并且还可以发现取消网络请求的操作也在CallExecuteObservable里面。
 
那么如果是用协程配合retrofit,网络请求又是怎么取消的呢?
//当只使用Retrofit的时候,接口是这样定义的 返回Call
@GET("article/list/1/json")
fun getHomeList() : Call<BaseResponse<Data>>
 
 
//当使用协程与Retrofit配合使用的时候,方法上加了个suspend
 @GET("article/list/1/json")
 suspend  fun getHomeList() : BaseResponse<Data>
 //发起网络请求
 viewModelScope.launch {
     withContext(Dispatchers.IO) {  getHomeList()   }
 }

3. 为啥使用viewModelScope,能自动取消网络请求呢?

当使用这种模式的时候,网络请求发起的包装类为:SuspendForBody (上面有提到哟)
static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
  private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
  private final boolean isNullable;
 
  SuspendForBody(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
      Converter<ResponseBody, ResponseT> responseConverter,
      CallAdapter<ResponseT, Call<ResponseT>> callAdapter, boolean isNullable) {
    super(requestFactory, callFactory, responseConverter);
    this.callAdapter = callAdapter;
    this.isNullable = isNullable;
  }
 
  @Override protected Object adapt(Call<ResponseT> call, Object[] args) {
    call = callAdapter.adapt(call);
 
    //noinspection unchecked Checked by reflection inside RequestFactory.
    Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
    //OkHttp Call.enqueue()带有异常,协程将拦截Continuation的后续调用
    try {
      return isNullable //为false
          ? KotlinExtensions.awaitNullable(call, continuation)
          : KotlinExtensions.await(call, continuation);
    } catch (Exception e) {
      return KotlinExtensions.yieldAndThrow(e, continuation);
    }
  }
}
再往下走
suspend fun <T : Any> Call<T>.await(): T {
  return suspendCancellableCoroutine { continuation ->
    continuation.invokeOnCancellation {
      cancel() //取消网络请求
    }
    enqueue(object : Callback<T> { //发起网络请求 这里是OkHttpCall的enqueue方法
      override fun onResponse(call: Call<T>, response: Response<T>) {
        if (response.isSuccessful) {
          val body = response.body()
          if (body == null) {
            val invocation = call.request().tag(Invocation::class.java)!!
            val method = invocation.method()
            val e = KotlinNullPointerException("Response from " +
                method.declaringClass.name +
                '.' +
                method.name +
                " was null but response body type was declared as non-null")
            continuation.resumeWithException(e)
          } else {
            continuation.resume(body)
          }
        } else {
          continuation.resumeWithException(HttpException(response))
        }
      }
 
      override fun onFailure(call: Call<T>, t: Throwable) {
        continuation.resumeWithException(t)
      }
    })
  }
} 
这里就可以看到看到了enqueue的执行,这里执行了Call类中的enqueue方法,并拿到返回值,通过continuation把结果和异常统统返回给协程的调用者。
continuation:顾名思义,继续、持续的意思,协程中的类,表示一个协程的延续,协程执行的时候会挂起,这个类就用于挂起完成之后的后续工作,看起来相当于一个回调。
继续跟进查看OkHttpCall的enqueue方法
call.enqueue(new okhttp3.Callback() {
  @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
    Response<T> response;
    try {
      response = parseResponse(rawResponse);//将网络请求成功后的Response转换成我们的实体类
    } catch (Throwable e) {
      throwIfFatal(e);
      callFailure(e);
      return;
    }
 
    try {
      callback.onResponse(OkHttpCall.this, response);//再回掉出去
    } catch (Throwable t) {
      throwIfFatal(t);
      t.printStackTrace(); // TODO this is not great
    }
  }

 

 流程图:

 

 

posted @ 2020-06-28 19:58  ts-android  阅读(278)  评论(0编辑  收藏  举报