本文将以retrofit运用流程的角度来解说retrofit的设计原理。(建议先看目录,再阅读文章)

先讲一下”上古时代”retrofit的用法。

后端文档:

  1. 接口 www.wanandroid.com/hotkey/json
  2. 恳求办法 GET
  3. 呼应示例
{
	"data": [{
		"id": 8,
		"link": "",
		"name": "逆向 加固",
		"order": 8,
		"visible": 1
	}],
	"errorCode": 0,
	"errorMsg": ""
}

客户端开发:

一,基本运用流程

1,界说呼应数据bean

//对应呼应的数据结构
class ApiResult<T> {
    var errorCode: String? = null
    var errorMsg: String? = null
    var data: T? = null
}
//对应data的数据结构
data class Info(
    val id: Int? = 0,
    val name: String? = "",
    val link: String? = "",
    val order: Int? = 0,
    val visible: Int? = 0
)

2,界说描绘网络恳求的接口

interface HotKeyApiInterface {
    @GET("/hotkey/json")
    fun getDataWithCall(): Call<ApiResult<List<Info>>>
}

3,创立Retrofit实例

val retrofit = Retrofit.Builder()
    .baseUrl("https://www.wanandroid.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

4,创立过程2中描绘网络恳求接口的署理

val apiProxy = retrofit.create(HotKeyApiInterface::class.java)

5,创立网络恳求Call

val call: Call  = apiProxy.getDataWithCall()

6,进行同步恳求或异步恳求

//进行同步恳求
val response = call.execute()
val apiResult = response.body() //得到咱们界说的ApiResult
//进行异步恳求
call.enqueue(object : Callback<ApiResult<List<Info>>> {
    override fun onResponse(
        call: Call<ApiResult<List<Info>>>,
        response: Response<ApiResult<List<Info>>>
    ) {
        val apiResult = response.body() //得到咱们界说的ApiResult
    }
    override fun onFailure(call: Call<ApiResult<List<Info>>>, t: Throwable) {
        TODO("Not yet implemented")
    }
})

二,retrofit中的注解类型

从上面过程2界说描绘网络恳求接口的代码为:

interface HotKeyApiInterface {
    @GET("/hotkey/json")
    fun getDataWithCall(): Call<ApiResult<List<Info>>>
}

这儿用@GET注解描绘当时恳求的恳求办法为GET恳求,恳求路径为”hotkey/json”。

retrofit中便是用注解来描绘咱们的恳求行为:如恳求办法、恳求参数等,然后在运行期间,经过解析注解封装一个恳求request,request中会带着恳求头、恳求地址、恳求办法等信息,最终调用okhttp完结真实的恳求。

整体来说,retrofit主要有三类注解:

1,描绘网络恳求办法的注解

@GET,@POST,@DELETE等

2,描绘网络恳求参数的注解

@HEAD,@Field,@Query等

3,其他类型注解

@Multipart,@Streaming,@FormUrlEncode

三,retrofit中的重要组件

查看retrofit的源码:

public final class Retrofit {
  final okhttp3.Call.Factory callFactory;
  final List<Converter.Factory> converterFactories;
  final List<CallAdapter.Factory> callAdapterFactories;
  final @Nullable Executor callbackExecutor;
  ...
}

上面列举了retrofit有几个重要的组件,咱们能够运用retrofit默许供给的这些组件完成,或许在实例化retrofit的时分,给它设置咱们自界说的组件完成,这些组件的具体原理在后面会具体解说。

1,callFactory

自界说装备的okHttpClient,retofit自身实际上并没有进行网络恳求的才能,它依赖OkHttp完结网络恳求。

2,converterFactories

数据转换器,用来将okhttp回来的response转换成咱们自界说的数据bean。

3,callAdapterFactories

适配器,适配器的回来值决定着上面过程二中接口的回来值。

4,callbackExecutor

回调履行器,切换到主线程回调成果。

四,动态署理

上面过程4 创立了描绘网络恳求接口的署理,代码如下:

val apiProxy = retrofit.create(HotKeyApiInterface::class.java)

查看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);
            }
          });
}

create办法调用Proxy.newProxyInstance()为接口HotKeyApiInterface生成动态署理,Proxy.newProxyInstance()源码如下,它是java供给的动态创立署理的api,接受三个参数:

  1. classLoader:类加载器。
  2. interfaces: 接口的class数组,创立的动态署理会完成这儿的接口。
  3. InvocationHandler:类InvocationHandler的一个完成,后面会剖析这个类的作用。
public static Object newProxyInstance(
    @RecentlyNullable ClassLoader loader, 
    @RecentlyNonNull Class<?>[] interfaces, 
    @RecentlyNonNull InvocationHandler h) throws IllegalArgumentException {
       ...
}

上面的动态署理会生成一个署理类Proxy,这儿的署理类并不是一个java文件,而是一个class文件,由于动态署理是在运行期间生成署理类的,署理类的class文件反编译成java文件后,代码大致如下。

//生成的署理类的源码
public final class $proxy0 extend Proxy implements HotKeyApiInterface {
    public $Proxy0(InvocationHandler handler) {
        super(handler);   //这儿的handler便是上面咱们传的第三个参数InvocationHandler,会赋值给它的父类Proxy的特点h
    }
    public final Call<ApiResult<List<Info>>> getDataWithCall() {
        this.h.invoke( ... ) //这儿的h为上面传进来的第三个参数InvocationHandler
    }
    ...
}
//体系类Proxy的源码
public class Proxy implements Serializable {
    protected InvocationHandler h;
    ...
}

总结一下:上面声明的apiProxy为$Proxy0的实例,即动态署理生成的署理类继承自Proxy且完成了咱们自界说的接口HotKeyApiInterface。

五,适配器CallAdapter

上面过程5 创立网络恳求Call的代码如下:

val call: Call  = apiProxy.getDataWithCall()

从前面文章的剖析中能够知道,这儿生成的apiProxy便是动态署理类 $Proxy0,它继承自Proxy且完成了接口HotKeyApiInterface,所以这儿的调用流程为:

  1. 调用apiProxy#getDataWithCall办法。
  2. 即履行署理类的getDataWithCall办法。
  3. 过程2的办法内部履行InvocationHandler的invoke办法,也便是会履行Retrofit#create办法中创立的InvocationHandler#invoke办法。

接着看InvocationHandler#invoke办法,源码如下:

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);   //要害点1
            }
          });
}

看要害点1处:履行loadServiceMethod办法的回来值invoke办法,即HtttpServiceMethod#invoke办法(怎么得出HtttpServiceMethod,大家能够自行调试):

//HtttpServiceMethod#invoke
@Override
final @Nullable ReturnT invoke(Object[] args) {
  Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
  return adapt(call, args);
}
//HtttpServiceMethod#adapter
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);

所以,HtttpServiceMethod#adapter的回来值便是咱们apiProxy.getDataWithCall()的回来值,adapter为一个笼统办法,它的完成类有三个:

  1. HtttpServiceMethod.CallAdapted:当apiProxy.getDataWithCall的回来值为Call的状况。
  2. HtttpServiceMethod.SuspendForResponse:这个是用来适配retrofit结合suspend,且回来值为Response的状况。
  3. HtttpServiceMethod.SuspendForBody:这个是用来适配retrofit结合suspend,且回来值为自定数据bean的状况。

上面的2, 3后续会单独出文章进行解说,由于咱们界说接口HotKeyApiInterface#getDataWithCall的回来类型为Call,所以这儿HtttpServiceMethod#adapter办法的完成类为CallAdapter,看看它的源码:

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
  private final CallAdapter<ResponseT, ReturnT> callAdapter;
  CallAdapted(
      RequestFactory requestFactory,
      okhttp3.Call.Factory callFactory,
      Converter<ResponseBody, ResponseT> responseConverter,
      CallAdapter<ResponseT, ReturnT> callAdapter) {
    super(requestFactory, callFactory, responseConverter);
    this.callAdapter = callAdapter;
  }
  @Override
  protected ReturnT adapt(Call<ResponseT> call, Object[] args) {   //要害点1
    return callAdapter.adapt(call);    //要害点2
  }
}

上面代码的要害点1处:这儿又有一个callAdapter,这个callAdapter才是咱们要解说的适配器CallAdapter,它在retrofit中的默许完成为:

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    @Nullable
    private final Executor callbackExecutor;
    DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }
    @Nullable
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
            return null;
        } else if (!(returnType instanceof ParameterizedType)) {
            throw new IllegalArgumentException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
        } else {
            final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType)returnType);
            final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : this.callbackExecutor;
            return new CallAdapter<Object, Call<?>>() {
                public Type responseType() {
                    return responseType;
                }
                public Call<Object> adapt(Call<Object> call) {   //要害点1
                    return (Call)(executor == null ? call : new ExecutorCallbackCall(executor, call));
                }
            };
        }
    }

看要害点1处,它回来一个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) {
    Objects.requireNonNull(callback, "callback == null");
    delegate.enqueue(
        new Callback<T>() {
          @Override
          public void onResponse(Call<T> call, final Response<T> response) {
            callbackExecutor.execute(
                () -> {
                  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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
          }
        });
  }
  @Override
  public boolean isExecuted() {
    return delegate.isExecuted();
  }
  @Override
  public Response<T> execute() throws IOException {
    return delegate.execute();
  }
}

ExecutorCallbackCall完成了接口Call,是Call类型,它其实是一个署理类,包含着真实的Call(OkHttpCall,retrofit中的),它便是咱们的apiProxy.getDataWithCall()的回来值。

六,网络恳求Call

1,网络恳求Call是什么

由前面的剖析可知apiProxy.getDataWithCall()回来的是ExecutorCallbackCall,它的源码如下:

static final class ExecutorCallbackCall<T> implements Call<T> {
  final Executor callbackExecutor;
  final Call<T> delegate;  //要害点1
  ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
    this.callbackExecutor = callbackExecutor;
    this.delegate = delegate;
  }
  @Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");
    delegate.enqueue(
        new Callback<T>() {
          @Override
          public void onResponse(Call<T> call, final Response<T> response) {
            callbackExecutor.execute(
                () -> {
                  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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
          }
        });
  }
  @Override
  public boolean isExecuted() {
    return delegate.isExecuted();
  }
  @Override
  public Response<T> execute() throws IOException {
    return delegate.execute();
  }
}

要害点1处:这个delegate是Retrofit中的OkHttpCall,源码如下:

final class OkHttpCall<T> implements Call<T> {
  private final RequestFactory requestFactory;
  private final Object[] args;
  private final okhttp3.Call.Factory callFactory;
  private final Converter<ResponseBody, T> responseConverter;
  private volatile boolean canceled;
  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;  //要害点2
  @GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
  private @Nullable Throwable creationFailure;
  @GuardedBy("this")
  private boolean executed;
}

看要害点2处:这个rawCall是Okhttp中的call。

总结一下:

  1. apiProxy.getDataWithCall()回来的call是ExcutorCallbackCall。
  2. ExcutorCallbackCall持有Retrofit中的OkHttpCall。
  3. Retrofit中的OKhttpCall持有OkHttp的Call。
  4. Retrofit发起网络恳求实际最终调用的是OkHttp的Call发起网络恳求。