初识一个框架之前,大概只知道其是用来解决什么问题。
而并不知道背后的原理以及原理的代码实现。
了解一个开源框架先了解背后的原理。
以Retrofit框架为例。
想要真正了解Retrofit框架背后的逻辑具体代表什么,先要明白HTTP协议原理。
这很有意义,只有这样才能融会贯通,形成体系,避免死记硬背,人的脑容量是有限的。
切入点:在使用框架的时候,离我们最近的方法。
以Retrofit为例,看下面的代码:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> call = service.listRepos("octocat");
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
}
});
这是Retrofit的一段使用示例,切入点是 call.enqueue(...)
在找到切入点之后就依托其继续深入。
以Retrofit为例, call.enqueue(...)
深入之后发现 enqueue
是一个接口的方法声明,深入失败。
如果将框架示例看做是主线逻辑代码,那么切入点就是示例的最后一行代码。
当深入切入点失败之后,回退到切入点之前的代码。
以Retrofit为例,寻找 enqueue
之前的关键代码
终于发现 retrofit.create(GithubService.class)
其返回GitHubService
接口的动态代理实现
,然后回到主线,就可以知道call
其实是动态代理调用listRepos(...)
方法返回的对象,但是不知道具体实现。
而listRepos(...)
方法其实是调用动态代理的InvocationHandler.invoke(...)
方法,所以继续深入invoke
方法。
一个方法的逻辑往往最后一行可以作为切入点
以InvocationHandler.invoke(...)
为例
@Override
public 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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
最后一行代码可以先看invoke方法,然后看loadServiceMethod方法,这样的一个阅读顺序分析得到Call
对象生成的大致思路:
ServiceMethod httpServiceMethod = (HttpServiceMethod Instance);
Call call = httpServiceMethod.invoke(args)
深入某个方法逻辑是一个横向的过程,而主线逻辑是一个纵向过程,当结束一段横向过程的时候,可以稍微停一下,并将横向结果代入主线,确保逻辑是否保持清晰。
然后可以再继续深入httpServiceMethod.invoke(args)
,循环上述方法一直追下去即可,就不一一详述了。
学习源码的一般方法大致就是如此:
找到纵向切入点,横向深入,回退,纵向梳理,横向深入、回退,纵向梳理。
反复如此这般即可。