用力拆一拆Retrofit
Retrofit是什么?
A type-safe HTTP client for Android and Java
一个应用于Android和Java类型安全的HTTP客户端(OkHttp的自我介绍是:OkHttp is an HTTP client that’s efficient by default;一个高效的HTTP客户端,当然Retrofit内部已经集成了OkHttp用于实际的网络请求,所以他也可以说是HTTP客户端了)
Retrofit的使用方法
- 创建一个Interface作为Web Service的请求集合,以注解(annotation)的形式添加请求方法的配置。
public interface NetWorkService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
- 用Retrofit创造Interface的实例对象。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")v
.build();
NetWorkService service =
retrofit.create(NetWorkService);
- 调用实例的方法并创建出相应的网路请求Call。
Call<List<Repo>> repos = service.listRepos("maidong");
- 使用Call.execute()或Call.enqueue()方法发起网络请求。
repos.enqueue(callback);
功能拆解
通过Retrofit.create()创建出Web Interface的实例对象,从而使得Interface的方法变得可用。
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);
}
});
}
Proxy.newProxyInstance会根据Interface(参数二,一般只有一个Interface,是我们调用Retrofit.create(ServiceIntetface.class)传进来的)创建一个实现类,该类实现了Ineteface的所有方法(代理了Inteface中定义的方法)。并且每个方法都会调用该类的成员变量InvocationHandler的invoce方法(Proxy.newProxyInstance的参数三)并且会把自己的方法信息传给invoke。
所以真正做事的是invoke方法,所以当service.listRepos(“maidong”);执行时就会调用invoke中的方法,其中关键代码只有一行 :
loadServiceMethod(method).invoke(args);
这行代码分可为两个关键方法:
- loadServiceMethod(method);
- invoke(args);
下面分别来看。
loadServiceMethod(method)
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;
}
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]);
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<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
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.");
}
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {//如果不是挂起函数,创建并返回一个CallAdapter
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
....
} else {
.....
}
上述源码很多,主要是进行注解的解析和初步处理,并且返回一个CallAdapter对象。稍后会介绍什么CallAdapter。我们继续…
接下来会调用invoke方法,先看源码:
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
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) {
return callAdapter.adapt(call);//返回的是一个OkHttp.call,接下来会分析。
}
}
上述代码最终返回的是callAdapter.adapt(call),也就是Call<List> repos = service.listRepos(“maidong”);左边这部分。从结果来看callAdapter.adapt(call)是个Call,那么接下来我们看看callAdapter.adapt做了什么事情,以及callAdapter是个啥,从哪来的?
CallAdapter是什么?
CallAdapter是CallAdapter.Factory的子类,是一个工厂类,如果我们设置了自定义的callAdapter这里也会生成其他类型的对象,如RxJava会最终生成Observable对象。
如果没单独配置的话,Retrofit会默认添加一个CallAdapter–DefaultCallAdapterFactory
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
.........
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
所以默认下,invoke方法中调用的adapt的实际的实现是:return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
返回值类型是 Call。
因为上述代码中DefaultCallAdapterFactory创建时有传executor,所以我们接着看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();
}
@Override
public void cancel() {
delegate.cancel();
}
@Override
public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override
public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override
public Request request() {
return delegate.request();
}
@Override
public Timeout timeout() {
return delegate.timeout();
}
}
是不是很熟悉,哈哈哈
所以service.listRepos(“maidong”)最终返回的是ExecutorCallbackCall。
还记得这个方法吗?
repos.enqueue(callback);
我们现在就很清楚的知道调用的是ExecutorCallbackCall里的enqueue方法。
接下来看下callbackExecutor是什么,是的,没错它就是创建DefaultCallAdapterFactory时一路传过来的Exector,线程池管理类,借助它可以实现线程切换到主线程,然后把网络响应结果交回给 Retrofit 的
Callback 。
接下来看看Retrofit是怎么实现的线程切换:
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
是通过Handler和主线程进行绑定,利用post发送到主线程中从而实现线程切换。
完结。