前言
-
为什么要看Retrofit源码?
- 因为目前项目使用的Retrofit网络请求。想去详细了解下。
-
这次阅读重点关注的点通过Create方法追踪工作流程
- 如何进行线程切换
- 用到反射如何去优化性能的
- 怎么解析参数和注解的
- 它针对Kotlin做哪些处理
-
本次阅读源码版本依赖
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
分析不对的地方请指出。。。
-
来张图
Retrofit 基本使用
-
创建接口
用于存放请求地址参数信息
interface ApiService { @GET("users/{user}/repos") fun listRepos(@Path("user") user: String?): Call<ResponseBody>? }
-
发起请求与Retrofit配置
class MainActivity : AppCompatActivity(), View.OnClickListener { private var mApiService: ApiService? = null private var mBinding: ActivityMainBinding? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mBinding = ActivityMainBinding.inflate(layoutInflater) setContentView(mBinding?.root) mBinding?.tvData?.setOnClickListener(this) //retrofit配置 val retrofit = Retrofit.Builder() .baseUrl("https://api.github.com/") .build() //接口实例 mApiService = retrofit.create(ApiService::class.java) } override fun onClick(v: View?) { requestData() } //发起请求 private fun requestData() { mApiService?.listRepos("brycecui")?.enqueue(object : Callback<ResponseBody> { override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) { Log.e("MainActivity", "onResponse:${response.body().toString()}") } override fun onFailure(call: Call<ResponseBody>, t: Throwable) { Log.e("MainActivity", "onFailure${t.localizedMessage}") } }) } }
问题分析
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);
}
});
}
-
注释①。获取对应平台
-
private static final Platform PLATFORM = findPlatform(); static Platform get() { return PLATFORM; } //得到Android平台 private static Platform findPlatform() { return "Dalvik".equals(System.getProperty("java.vm.name")) ? new Android() // : new Platform(true); } //省略部分代码 static final class Android extends Platform { Android() { super(Build.VERSION.SDK_INT >= 24); } @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } //省略部分代码 static final class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { //切换线程 handler.post(r); } } }
会得到一个Android平台。
-
-
注释②。会返回
false
走到loadServiceMethod
方法-
看下
loadServiceMethod
源码private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { //解析数据得到ServiceMethod result = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result; }
如果(线程安全的
ConcurrentHashMap
)缓存中有直接返回。没有解析并储存之后返回ServiceMethod
。 -
看下他解析数据的过程源码
abstract class ServiceMethod<T> { static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); //省略部分代码 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract @Nullable T invoke(Object[] args); }
ServiceMethod
是一个抽象类。-
RequestFactory的parseAnnotations源码
//建造者模式 static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); }
-
RequestFactory构造方法
RequestFactory(Builder builder) { method = builder.method; baseUrl = builder.retrofit.baseUrl; httpMethod = builder.httpMethod; relativeUrl = builder.relativeUrl; headers = builder.headers; contentType = builder.contentType; hasBody = builder.hasBody; isFormEncoded = builder.isFormEncoded; isMultipart = builder.isMultipart; parameterHandlers = builder.parameterHandlers; isKotlinSuspendFunction = builder.isKotlinSuspendFunction; }
-
RequestFactory.Builder和它的build方法
Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; //通过 反射得到注解、参数等信息。 this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); } RequestFactory build() { for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) { parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); } //省略部分空检查代码 return new RequestFactory(this); }
-
我看看下返回的RequestFactory都有啥。看下图是使用上面简单使用的例子debug的
baseUrl:就是retrofit传过来的baseUrl
httpMethod:我们用的GET注解。(用的POST就是POST)我们可以看下如何进行解析的
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); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof retrofit2.http.Headers) { String[] headersToParse = ((retrofit2.http.Headers) annotation).value(); if (headersToParse.length == 0) { throw methodError(method, "@Headers annotation is empty."); } headers = parseHeaders(headersToParse); } else if (annotation instanceof Multipart) { if (isFormEncoded) { throw methodError(method, "Only one encoding annotation is allowed."); } isMultipart = true; } else if (annotation instanceof FormUrlEncoded) { if (isMultipart) { throw methodError(method, "Only one encoding annotation is allowed."); } isFormEncoded = true; } }
根据使用instanceof 判断是那种注解进行对应的方法解析。也就是parseHttpMethodAndPath方法。
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { //省略httpMethod空异常检查 this.httpMethod = httpMethod; this.hasBody = hasBody; if (value.isEmpty()) { return; } // Get the relative URL path and existing query string, if present. int question = value.indexOf('?'); if (question != -1 && question < value.length() - 1) { // Ensure the query string does not have any named parameters. String queryParams = value.substring(question + 1); Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams); if (queryParamMatcher.find()) { throw methodError( method, "URL query string \"%s\" must not have replace block. " + "For dynamic query parameters use @Query.", queryParams); } } this.relativeUrl = value; this.relativeUrlParamNames = parsePathParameters(value); } /***********************************手动分割线******************************************/ static Set<String> parsePathParameters(String path) { Matcher m = PARAM_URL_REGEX.matcher(path); Set<String> patterns = new LinkedHashSet<>(); while (m.find()) { patterns.add(m.group(1)); } return patterns; }
parseHttpMethodAndPath
的value是 请求方法注解里面的值。对应示例中是users/{user}/repos。由于没有?
所以不会走if语句。relativeUrl也就等于users/{user}/repos
-
-
-
在看下ServiceMethod返回的HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)方法
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(); 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); } }
isKotlinSuspendFunction用来判断是否使用kotlin协程请求。
true代表使用挂起函数。那么会创建SuspendForResponse和SuspendForBody。分别是返回值为Ressponse<T>和ResponseBody。
分别在内部调用了扩展函数。使用协程切换线程
//返回值为Ressponse使用 suspend fun <T> Call<T>.awaitResponse(): Response<T> { return suspendCancellableCoroutine { continuation -> continuation.invokeOnCancellation { cancel() } enqueue(object : Callback<T> { override fun onResponse(call: Call<T>, response: Response<T>) { continuation.resume(response) } override fun onFailure(call: Call<T>, t: Throwable) { continuation.resumeWithException(t) } }) } } //返回值为ResponseBody使用。成功直接返回ResponseBody suspend fun <T : Any> Call<T>.await(): T { return suspendCancellableCoroutine { continuation -> continuation.invokeOnCancellation { cancel() } enqueue(object : Callback<T> { 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) } }) } }
最终会返回一个CallAdapted<>,而CallAdapted<>是继承的HttpServiceMethod。
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); } }
而loadServiceMethod(method)的invoke(args)方法。会调用CallAdapted的adapte方法。而这个CallAdapted是由HttpServiceMethod的 createCallAdapter方法创建的。也就是retrofit的addCallAdapterFactory方法添加的。示例中我们没有添加所以走得是默认的CallAdapted。在retrofit的Builder类中可以找到
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//这添加一个平台默认的CallAdapter并且传一个线程池callbackExecutor
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
//可以看到defaultCallbackExecutor也是由平台默认的额
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
我们看下平台platform这俩个默认方法。
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
继续看DefaultCallAdapterFactory
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
//省略空检查
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
//当时kotlin协程请求时返回okhttpcall 否则返回ExecutorCallbackCall
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
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");
//(OkHttp封装类)OkHttpCall的enqueue方法进行请求
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();
}
}
}
也就是说我们示例中的mApiService?.listRepos("brycecui")?.enqueue()最终到了这里。delegate他是 Call<T>接口。它的实现类是OkHttpCall。怎么知道不是别的实现类。上面我们通过代码追踪知道了loadserviceMethod.invoke.实际是调用了 抽象类ServiceMethod的实现类HttpServiceMethod的invoke方法。也就是下面这个方法。下面调用了adapt方法并把OkHttpCall传了过去。最终也就是通过DefaultCallAdapterFactory的get方法的adapt创建一个ExecutorCallbackCall传递的。
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
看下 callbackExecutor.execute。线程切换关键所在。
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(r);切换到主线程。
总结
-
如何切换线程
- kotlin 使用协程
- 默认使用handler
-
用到反射如何优化性能的
- 使用map缓存避免多次反射浪费性能
-
如何解析参数注解
- 使用反射解析、正则匹配
-
针对kotlin做了哪些处理
- 判断是否使用kotlin并且针对返回值是否只需要body