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