Retrofit源码分析&小结

Retrofit源码分析&小结

简介

Retrofit是对Okhttp网络请求的二次封装,通过注解+动态代理的方式,简化了Okhttp的使用,使得通过简单的配置就可以像调用接口一样去请求网络接口;除此之外Retrofit还支持RxJava和kotlin的协程

基本使用

  1. 引入依赖库
//网络请求
implementation 'com.squareup.retrofit2:retrofit:2.9.0'//Retrofit基本库
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'//用于将结果转换成对象
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//用于转换成RxJava支持的Observer对象
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'//RxJava对Android的支持
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'//Okhttp日志拦截器,用于打印接口请求相关log
//协程
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'//Retrofit对Kotlin协程的支持
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'//协程对Android的支持
implementation('androidx.lifecycle:lifecycle-runtime-ktx:2.6.0-alpha02')//协程对LifeCycle的支持
  1. 定义一个用于网络请求的服务接口
package com.example.myapplication.retrofit

import android.service.autofill.UserData
import io.reactivex.Observable
import retrofit2.Call
import retrofit2.http.*

interface IUserServer {
    /**
     * 以GET方式请求
     */
    @GET("getUserInfo/")
    fun getUserInfo(@Query("userId") userId: String): Call<UserData>

    /**
     * 以POST方式请求,并结合RxJava
     */
    @POST("getUserInfo/")
    @FormUrlEncoded
    fun getUserInfoByRxJava(@Field("userId") userId: String): Observable<UserData>

    /**
     * 结合kotlin协程完成线程切换
     */
    @GET("banner/json")
    suspend fun getUserInfoBySuspend2(@Query("userId") userId: String): UserData

}
  1. 创建Retrofit对象和自定义接口代理实现对象
val retrofit = Retrofit.Builder()
    .baseUrl("http://www.xxx.com/")
    .addConverterFactory(GsonConverterFactory.create())//支持Gson
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//支持Rxjava
    .build()
val server = retrofit.create(IUserServer::class.java)
  1. 普通发起网络请求
val userInfo = server.getUserInfo("1").execute()//同步执行
server.getUserInfo("1").enqueue(object : Callback<UserData> {//异步执行
    override fun onResponse(call: Call<UserData>, response: Response<UserData>) {
        //网络请求返回结果
    }

    override fun onFailure(call: Call<UserData>, t: Throwable) {
        //网络请求错误
    }
})
  1. 结合RxJava
server.getUserInfoByRxJava("1").subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<UserData> {
    override fun onSubscribe(d: Disposable?) {
        //网络请求前
    }

    override fun onNext(value: UserData?) {
        //网络请求返回结果
    }

    override fun onError(e: Throwable?) {
        //网络请求错误
    }

    override fun onComplete() {
        //网络请求结束
    }
})
  1. 结合Kotlin协程
lifecycleScope.launch {
    val userInfo = withContext(Dispatchers.IO) {
        val userInfo = server.getUserInfoBySuspend2("1")//子线程中请求网络
    }
    //回到主线程
    Log.i("testRetrofit", "userInfo:$userInfo")
}

核心源码分析

1. Retrofit.create方法,根据注解为我们声明的接口创建动态代理

```
public <T> T create(final Class<T> service) {
validateServiceInterface(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);
            }
            args = args != null ? args : emptyArgs;
            return platform.isDefaultMethod(method)//判断该方法是否用户自定义的
                ? platform.invokeDefaultMethod(method, service, proxy, args)
                : loadServiceMethod(method).invoke(args);//开始解析该方法并返回接口请求对象,比如Call、Observable(需结合Rxjava)
          }
        });
}
```
  • 在validateServiceInterface方法中,如果配置了Retrofit.Builder().validateEagerly(true),会立刻根据注解解析接口中定义的所有方法,如果是false,则会等待方法调用时才会解析接口中的方法;

    设置为true的好处是在创建接口代理时就能检查出各个方法配置的注解、返回值等是否正确,如果为默认的false,则只有在方法调用时才能发现问题;

    所以建议在debug阶段设置为true便于及早发现问题,release阶段设置false以提高性能

    private void validateServiceInterface(Class<?> service) {
        ... ...
        if (validateEagerly) {
          Platform platform = Platform.get();
          for (Method method : service.getDeclaredMethods()) {//遍历所有方法,根据注解进行解析
            if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
              loadServiceMethod(method);
            }
          }
        }
    }
    
  • 默认实现中接口返回的Call实际上是一个Retrofit中定义的一个接口,定义了同步请求和异步请求的方法;

    public interface Call<T> extends Cloneable {
      ... ...
      /**
       * Synchronously send the request and return its response.
       *
       * @throws IOException if a problem occurred talking to the server.
       * @throws RuntimeException (and subclasses) if an unexpected error occurs creating the request or
       *     decoding the response.
       */
      Response<T> execute() throws IOException;
    
      /**
       * Asynchronously send the request and notify {@code callback} of its response or if an error
       * occurred talking to the server, creating the request, or processing the response.
       */
      void enqueue(Callback<T> callback);
      ... ...
    }
    
  • Call的实现类根据是否有注解@SkipCallbackExecutor来决定,当有该注解时,Call的实现类是OkHttpCall.java,里面封装了OkHttp的网络请求,如果没有该注解,则Call实现类是DefaultCallAdapterFactory.ExecutorCallbackCall;这个类仅仅是个代理类,真正实现网络请求的还是OkHttpCall;
    代理类存在的意义是Okhttp进行异步请求返回结果后,会先通过Handler将线程切换到主线程再返回结果

    final class OkHttpCall<T> implements Call<T> {
        @Override
        public void enqueue(final Callback<T> callback) {
            ...
            okhttp3.Call call;
            call.enqueue(
            new okhttp3.Callback() {
              @Override
              public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
              }
              @Override
              public void onFailure(okhttp3.Call call, IOException e) {
                callFailure(e);
              }
            }
            ...
        }
    
        @Override
        public Response<T> execute() throws IOException {
        okhttp3.Call call;
        ...
        return parseResponse(call.execute());
      }
    }
    
    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;//在主线程执行,实现类是Platform.Android.MainThreadExecutor
        final Call<T> delegate;//这个实现类是OkHttpCall
    
        @Override
        public void enqueue(final Callback<T> callback) {
          delegate.enqueue(
              new Callback<T>() {
                @Override
                public void onResponse(Call<T> call, final Response<T> response) {
                  callbackExecutor.execute(() -> {
                        //切换到主线程执行
                          callback.onResponse(ExecutorCallbackCall.this, response);
                        }
                      });
                }
    
                @Override
                public void onFailure(Call<T> call, final Throwable t) {
                  //切换到主线程执行
                  callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
                }
              });
        }
    
        @Override
        public Response<T> execute() throws IOException {
          return delegate.execute();//在当前所在线程执行
        }
    }
    

2. 注解的解析过程和使用

  • 在Retrofit.create方法中,loadServiceMethod方法中会先从缓存中查找ServiceMethod对象,如果之前有解析过则直接返回,如果没有则调用ServiceMethod.parseAnnotations方法返回一个ServiceMethod对象

    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;
    }
    
  • 接着会调用RequestFactory.parseAnnotations方法真正进行注解的解析,并构建一个HttpServiceMethod对象返回

    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);
    }
    
  • RequestFactory.Builder中解析方法中的注解,可以理解为RequestFactory对象保存着所有请求的数据

    final class RequestFactory {
      static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
        return new Builder(retrofit, method).build();
      }
      static final class Builder {
        final Annotation[] methodAnnotations;//方法上的注解
        final Annotation[][] parameterAnnotationsArray;//方法参数上的注解
        final Type[] parameterTypes;//参数类型
        @Nullable String httpMethod;//请求的方式get、post等
        @Nullable String relativeUrl;//解析处理后的请求接口
        @Nullable Headers headers;//封装的请求头信息
        boolean isKotlinSuspendFunction; //用于标记是否kotlin协程中suspend方法
        ...
        private Headers parseHeaders(String[] headers) {}//解析请求头信息
        private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) //解析请求方式和接口路径
        private void parseMethodAnnotation(Annotation annotation) {//解析方法上的注解
          if (annotation instanceof DELETE) {
            parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
          } else if (annotation instanceof GET) {
            parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
          } else if (annotation instanceof HEAD) {
            parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
          } else if (annotation instanceof PATCH) {
            parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
          } else if (annotation instanceof POST) {
            parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
          } else if (annotation instanceof PUT) {
            parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
          }
          ...
        }
        private ParameterHandler<?> parseParameterAnnotation(){//解析参数上注解
            if (annotation instanceof Path) {
            } else if (annotation instanceof Query) {
            } else if (annotation instanceof QueryName) {
            } else if (annotation instanceof QueryMap) {
            } else if (annotation instanceof Header) {
            } else if (annotation instanceof HeaderMap) {
            } else if (annotation instanceof Field) {
            } else if (annotation instanceof FieldMap) {
            }  else if (annotation instanceof Body) {
            }
            ...
        }
      }
    }
    
  • 请求参数的使用,是在真正发起网络请求OkhttpCall.createRawCall()方法中创建Okhttp Call对象的时候,通过RequestFactory.create方法将所有请求参数封装成OkHttp的Request对象

class OkHttpCall{
    private okhttp3.Call createRawCall() throws IOException {
        okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
        return call;
    }
}
class RequestFactory{
    okhttp3.Request create(Object[] args) throws IOException {
        RequestBuilder requestBuilder =
            new RequestBuilder(
                httpMethod,
                baseUrl,
                relativeUrl,
                headers,
                contentType,
                hasBody,
                isFormEncoded,
                isMultipart);

        if (isKotlinSuspendFunction) {//协程suspen方法会自动在最后面加一个Continuation对象类型参数,所以实际请求时要去掉
          // 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]);
        }
        //构建okhttp3.Request对象
        return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
    }
}

3. RxJava2CallAdapterFactory:对Rxjava的支持,将默认返回的的Call对象转换成Observer对象

  • 当调用接口方法的时候,通过动态代理默认会调用HttpServiceMethod.CallAdapted的invoke方法,而CallAdapted继承自HttpServiceMethod,并重写了adapt方法;
    adapt方法用于封装Call对象并将结果转化成我们定义的接口方法所声明的返回对象
class HttpServiceMethod{
 @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);

  static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;//默认的适配器是通过DefaultCallAdapterFactory动态生成的CallAdapter实现类

    CallAdapted(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, ReturnT> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;//通过RxJava2CallAdapterFactory生成的Rxjava2适配器RxJava2CallAdapter
    }

    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);//调用适配器,将返回结果转换成我们定义的返回类型,比如默认是返回Call,Rxjava返回的是Observer对象
    }
  }
}
  • RxJava2CallAdapterFactory在创建时,可以选择调用create、createAsync、createWithScheduler(Scheduler)方法进行创建,他们的主要区别是create是调用Call.execute方法请求网络,也就是在当前线程执行;
    而createAsync则是调用Call.enqueue方法请求网络,也就是异步请求;createWithScheduler可以传入一个Scheduler,指定网络请求在哪个线程上执行,通过observable.subscribeOn(scheduler)实现
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
  /**
   * Returns an instance which creates synchronous observables that do not operate on any scheduler
   * by default.
   */
  public static RxJava2CallAdapterFactory create() {
    return new RxJava2CallAdapterFactory(null, false);
  }

  /**
   * Returns an instance which creates asynchronous observables. Applying
   * {@link Observable#subscribeOn} has no effect on stream types created by this factory.
   */
  public static RxJava2CallAdapterFactory createAsync() {
    return new RxJava2CallAdapterFactory(null, true);
  }

  public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
    if (scheduler == null) throw new NullPointerException("scheduler == null");
    return new RxJava2CallAdapterFactory(scheduler, false);
  }

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    ...
    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }
}
  • 调用RxJava2CallAdapter.adapt方法,将Call传入并返回Observer
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
    @Override public Object adapt(Call<R> call) {
    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);
        }
        ...
        return observable;
    }
}
  • 当外部调用Observer的subscribe方法时,后就会立刻执行CallExecuteObservable/CallExecuteObservable里的subscribeActual方法,从而调用Call的execute或者enqueue方法实现网络请求
class Observable{
    public final void subscribe(Observer<? super T> observer) {
        subscribeActual(observer);
    }
}

final class CallExecuteObservable<T> extends Observable<Response<T>> {
    @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
        Call<T> call = originalCall.clone();
        Response<T> response = call.execute();//发起网络请求并返回结果
        if (!call.isCanceled()) {//传递给onNext方法
            observer.onNext(response);
          }
          if (!call.isCanceled()) {
            terminated = true;
            observer.onComplete();
          }
    }
}

4. GsonConverterFactory:网络请求返回结果的处理

  • 在OkHttpCall发起网络请求后,会调用parseResponse方法解析返回结果,然后通过结果转换器进行转换,默认转换器是BuiltInConverters,如果配置了GsonConverterFactory,则支持转换成我们自定义对象,实现类是GsonResponseBodyConverter
class OkHttpCall{
    @Override
  public Response<T> execute() throws IOException {
    okhttp3.Call call;
    call = getRawCall();
    ...
    return parseResponse(call.execute());
  }

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    ...
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      //调用结果转换器进行转换,这里会根据声明方法返回值类型选择不同转换器,比如返回默认的ResponseBody,则使用自带的BuiltInConverters转换,返回自定义对象则会使用GsonResponseBodyConverter进行转换
      T body = responseConverter.convert(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;
    }
  }
}
  • Retrofit自带的默认转换器BuiltInConverters,支持处理返回类型是ResponseBody/Void 或者kotlin的Unit
final class BuiltInConverters extends Converter.Factory {
  /** Not volatile because we don't mind multiple threads discovering this. */
  private boolean checkForKotlinUnit = true;

  @Override
  public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
      Type type, Annotation[] annotations, Retrofit retrofit) {
    if (type == ResponseBody.class) {
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    if (checkForKotlinUnit) {
      try {
        if (type == Unit.class) {
          return UnitResponseBodyConverter.INSTANCE;
        }
      } catch (NoClassDefFoundError ignored) {
        checkForKotlinUnit = false;
      }
    }
    return null;
  }
}
  • 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 {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}

5. 对kotlin协程的支持

  • 判断是否kotlin suspend方法,在kotlin中suspend修饰的方法在编译成字节码并反编译成java代码后会发现方法参数里最后会多一个Continuation类型的参数,用于对协程的支持
kotlin字节码反编译后的java代码
public interface IUserServer {
    ... ...

   @GET("banner/json")
   @Nullable
   Object getUserInfoBySuspend2(@Query("userId") @NotNull String var1, @NotNull Continuation var2);
}
  • Retrofit在RequestFactory解析方法参数时做判断
class RequestFactory{
    class Builder{
        boolean isKotlinSuspendFunction;
        private @Nullable ParameterHandler<?> parseParameter(
        int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
            try {
                if (Utils.getRawType(parameterType) == Continuation.class) {//判断是否suspend协程方法
                  isKotlinSuspendFunction = true;
                  return null;
                }
            } catch (NoClassDefFoundError ignored) {
            }
        }
    }
}
  • 根据方法返回类型,返回不同的HttpServiceMethod,当suspend方法直接返回自定义数据类型时(比如 UserData),返回的是SuspendForBody对象; 如果方法返回的是Response,则返回SuspendForResponse对象,这两个返回对象其实差不多,只是返回类型不一样
class HttpServiceMethod{
    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
        boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
        boolean continuationWantsResponse = false;
        if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
            // Unwrap the actual body type from Response<T>.
            responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
            continuationWantsResponse = true;
        }
        if (continuationWantsResponse) {
          //返回Response<UserData>类型结果
          return (HttpServiceMethod<ResponseT, ReturnT>)
              new SuspendForResponse<>(
                  requestFactory,
                  callFactory,
                  responseConverter,
                  (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
        } else {
          //返回UserData类型结果
          return (HttpServiceMethod<ResponseT, ReturnT>)
              new SuspendForBody<>(
                  requestFactory,
                  callFactory,
                  responseConverter,
                  (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
                  continuationBodyNullable);
        }
    }
}
  • 继续以SuspendForBody分析,在adapt方法被调用时,Retrofit会调用kotlin的扩展方法await/awaitNullable
static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
    private final boolean isNullable;

    @Override
    protected Object adapt(Call<ResponseT> call, Object[] args) {
      call = callAdapter.adapt(call);//这里是默认的DefaultCallAdapterFactorys产生的Adapter
      //获取suspend最后一个参数用于协程
      Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
      try {//调用Retrofit使用kotlin对Call类的扩展方法
        return isNullable //返回的对象是否可为空
            ? KotlinExtensions.awaitNullable(call, continuation)
            : KotlinExtensions.await(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
}
  • kotlin对Call方法扩展解析,协程方法中会异步发起网络请求并返回结果,当结束后会恢复到父协程地方继续执行
//这里是suspend方法,执行时协程会挂起
suspend fun <T : Any> Call<T>.await(): T {
  return suspendCancellableCoroutine { continuation ->
    continuation.invokeOnCancellation {
      cancel()//设置协程取消时的回调,调用Call的cancel方法
    }
    enqueue(object : Callback<T> {//调用Call方法异步请求网络
      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)//恢复协程并抛出异常
      }
    })
  }
}

小结

  • Retrofit实现原理:
    答:Retrofit通过Create方法创建我们自定义接口实例时,会为我们接口创建一个动态代理;当调用接口方法的时候,会先根据配置的注解解析这个方法的信息,包括请求路径、请求参数、返回值等等,并把解析后的信息封装成对象并缓存起来;
    然后根据方法的信息封装成一个Call对象,这个Call对象的默认实现类是OkHttpCall,内部是通过Okhttp发起同步或者异步网络请求;
    然后调用Call的execute同步或者enqueue异步方法进行网络请求,返回结果后,会调用转换器对结果进行转换,默认是返回ResponseBody,也可以通过配置Gson转换器转成我们自定义类型;
    如果需要对RxJava支持,返回Observer对象,则是需要配置一个Rxjava的CallAdapter,在适配器中将Call对象封装到Observer对象中并返回,当Observer的subscribe方法调用时会触发Call的网络请求操作,最后通过RxJava对结果分发;
    如果需要对kotlin协程支持,Retrofit在对方法解析时会判断是否suspend方法,如果是的话,会执行Call的kotlin扩展方法,扩展方法也是suspend类型,在扩展方法中会挂起协程,通过Call对象执行网络请求操作,最后通过Continuation.resume方法恢复协程到父协程调用的地方

  • 静态代理和动态代理的区别?
    答:静态代理是指在代码编写的时候,代理类和被代理类的关系就确定了,编译后也会生成代理类字节码文件;而动态代理是指在运行时期,动态的通过反射方式为被代理的接口生成一个代理类,当调用这个接口的方法时,都会进入InvokeHandler的invoke方法中,从而实现对这个被代理接口的统一处理;
    静态代理适合被代理的类比较少的情况,如果代理的类比较多,而且不需要做统一处理,则动态代理方便很多

  • Retrofit返回结果是如何切换到主线程的?
    答:Retrofit会通过系统属性来判断是否Android平台,如果是Android平台,则会创建一个执行器,内部会创建一个主线程Looper的Handler,当网络请求结束返回结果时,会封装一个Runnable通过这个主线程Handler去执行,从而切换到主线程;
    或者通过RxJava或者协程进行线程切换

  • 对Kotlin协程(suspend方法)的支持

    • 判断协程方法条件:判断方法最后一个参数是否是Continuation.class类型
    • Retrofit使用kotlin对Call类扩展了suspend方法,在suspend方法中执行Call的网络请求,然后通过Continuation的resume方法恢复协程挂起并返回结果
    • 什么时候切回主线程的?在协程中调用continuation.resume方法后会自动回到它父协程所在线程,也就是主线程继续执行

猜你喜欢

转载自blog.csdn.net/guangdeshishe/article/details/129903236