一、retrofit和okhttp初始化配置
1.Retrofit配置
- client:网络请求引擎
- addCallAdapterFactory:响应网络数据后,包装数据后期望类型,可加多个
- addConverterFactory:数据解析转换类型,常用:GsonConverterFactory.create()
- baseUrl:主要url必须以 "/" 结尾,格式有强校验
2.Okhttp配置
常规配置拦截器、网络连接、读写超时不过多介绍,主要说明几个实用的:
- proxy:代理设置,Proxy.NO_PROXY设置该类型可以防止应用被抓包
- eventListener:监听网络链路生命周期各个阶段时间消化,可做为网络数据监听使用
- getDispatcher$okhttp().setMaxRequestsPerHost:设置单个域名最大请求数
- connectionPool:自定义网络连接复用池个数以及复用时长
- setDns$okhttp:自定义解析DNS
二、网络请求发起
1.通过retrofit的实例调用create方法或者到service的实例,然后调用对应方法。
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);
}
});
}
首先通过validateServiceInterface方法校验class泛型参数是否是interface,而且会校验是否是一个不为空定义的interface,必须是interface的原因是需要通过动态代理去反射生成实例,动态代理必须是interface(java的单继承、多接口实现)。
2.通过loadServiceMethod方法获取一个HttpServiceMethod,该方法内有一个复用逻辑。
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;
}
通过静态方法parseAnnotations解析得到对应的实例对象。
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);
}
首先会通过method去构建一个RequestFactory,然后去调用hasUnresolvableType校验方法是否有有效的返回值(因为一个网络请求发出必须有值给到响应),最后去通过parseAnnotations方法构建一个有效的ServiceMethod。
思考:RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
为什么不放在校验条件之后,如下述条件不成立,这个地方为无效创建。
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) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
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);
}
}
这个方法整体执行逻辑是先校验该方法是否kotlin的suspend得到对应的adapterType,然后拿到方法的所有注解列表,去得到实际的CallAdapter。调用createCallAdapter去创建CallAdapter,然后会继续调用retrofit的callAdapter->nextCallAdapter方法,继续看代码:
public CallAdapter<?, ?> nextCallAdapter(
@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
Objects.requireNonNull(returnType, "returnType == null");
Objects.requireNonNull(annotations, "annotations == null");
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;
}
}
该方法会先去校验是否有返回值和注解,然后会去在callAdapterFactories里边找对应callAdapter,看到这里callAdapterFactories里的callAdapter就和我们初始化retrofit中加的addCallAdapterFactory有关系了。最后就包装生成一个ServiceMethod实例了。
再回到动态方法里通过serviceMethod对象invoke方法去真正执行网络调用。
loadServiceMethod(method).invoke(args);
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}