retrofit

原理-动态代理

*Retrofit通过 反射构建一个 接口的 实现类(动态代理本质就是反射),其中每个重写方法被调用时,都会回调到InvocationHandler.invoke中,invoke回调时(只要是不是object类中的方法)都会通过 获取到的方法的注解、方法的名称、方法的返回值、方法参数的注解、方法参数类型等等所需信息, 解析成一个ServiceMethod对象(放入缓存池),ServiceMethod根据获取到的方法信息,构建OkHttp请求,并将结果通过converter转换后回调给最初传入的Callback*

val service = retrofit.create(GitHubService::class.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public <T> T create(final Class<T> service) {
//校验数据,是否不是默认方法(公共非抽象方法)
validateServiceInterface(service);
return (T)
//代理模式,通过反射 构建一个 实现了所有 传入interface的方法 的类,该类中每个方法都调用了传入InvacationHandler对象中invoke方法。
//即反射 构建一个 interfaces的实现类,该实现类中每个重写方法都由将自身的信息传给invoke方法,由invoke方法代理执行。
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);
}
});
}

动态代理原理

核心 API 是 Proxy 类和 InvocationHandler 接口。

它的原理是利用反射机制在运行时生成代理类的字节码。

动态代理的原理就是一个代理类文件的动态加载过程,由于JVM可以通过.class文件的二进制信息加载class对象的,那么如果我们在代码运行时,遵循.class文件的格式和结构,生成相应的二进制数据,然后再把这个二进制数据通过JVM加载成对应的class对象,有了class对象,我们就可以在运行时通过反射创建出代理对象的实例,这样就完成了在代码运行时,动态的创建一个代理对象的能力,这就是动态代理的原理。

https://juejin.cn/post/6974018412158664734

使用

  1. 创建一个interface作为Web Service 的请求集合,在里面用注解(Annotation)写入需要配置
    的请求方法
1
2
3
4
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
  1. 在正式代码里用 Retrofit 创建出interface的实例
1
2
3
4
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
  1. 调用创建出的Service实例的对应方法,创建出相应的可以用来发起网络请求的call 对象
    Call<List<Repo>> repos = service.listRepos("octocat");
  1. 使用Call.execute()或者call.enqueue()来发起请求
    repos.enqueue(callback);
Author

white crow

Posted on

2021-04-08

Updated on

2024-04-24

Licensed under