Android组件化最佳实践 ARetrofit原理

0
回复
384
查看
[复制链接]

3

主题

3

帖子

21

安币

初级码农

Rank: 1

发表于 2019-1-30 18:40:01 | 显示全部楼层 |阅读模式
如果对本篇文章感兴趣,请前往,原文地址:http://www.apkbus.com/blog-974254-79468.html

Hello,各位伟大的程序猿们,提前给各位拜年了,祝大家在新的一年收获满满、挣钱多多、猪年吉祥。开源ARetrofit大约半年左右的时间,没有任何推广和介绍,今天一看也有160 的stars了,这里非常感谢大家的支持。趁着年关降至,也想写一点东西来介绍一下这个框架。无论是ARetrofit的用户也好,还是对源码感兴趣的同学也好,希望能从这篇文章中有所收获。## 简介ARetrofit是一款针对Android组件之间通信的框架,实现组件之间解耦的同时还可以通信。源码链接:https://github.com/yifei8/ARetrofit欢迎star、issues、fork## 组件化Android组件化已经不是一个新鲜的概念了,出来了已经有很长一段时间了,大家可以自行Google,可以看到一堆相关的文章。简单的来说,所谓的组件就是Android Studio中的Module,每一个Module都遵循高内聚的原则,通过ARetrofit来实现无耦合的代码结构,如下图:![Picture](//upload-images.jianshu.io/upload_images/2116778-6433e9a8780259a9.png)每一个Module可单独作为一个project运行,而打包到整体时Module之间的通信通过ARetrofit完成。## ARetrofit原理讲原理之前,我想先说说为什么要ARetrofit。开发ARetrofit这个项目的思路来源其实是Retrofit,Retrofit是Square公司开发的一款针对Android网络请求的框架,这里不对Retrofit展开来讲。主要是Retrofit框架使用非常多的设计模式,可以说Retrofit这个开源项目将Java的设计模式运用到了极致,当然最终提供的API也是非常简洁的。如此简洁的API,使得我们APP中的网络模块实现变得非常轻松,并且维护起来也很舒服。因此我觉得有必要将Android组件之间的通信也变得轻松,使用者可以优雅的通过简洁的API就可以实现通信,更重要的是维护起来也非常的舒服。ARetrofit基本原理可以简化为下图所示:![Picture](//upload-images.jianshu.io/upload_images/2116778-e64fb90c6295710b.png)- 通过注解声明需要通信的Activity/Fragment或者Class- 每一个module通过annotationProcessor在编译时生成待注入的RouteInject的实现类和AInterceptorInject的实现类。这一步在执行app[build]时会输出日志,可以直观的看到,如下图所示:```注: AInjecton::Compiler >>> Apt interceptor Processor start... > Apt route Processor start... > Apt route Processor succeed > ========== Transform scan start ===========TransformPluginLaunch >>> ========== Transform scan end cost 0.238 secs and start inserting ===========TransformPluginLaunch >>> Inserting code to jar >> /Users/yifei/as_workspace/ARetrofit/app/build/intermediates/transforms/TransformPluginLaunch/release/8.jarTransformPluginLaunch >>> to class >> com/sjtu/yifei/route/RouteRegister.classInjectClassVisitor >>> inject to class:InjectClassVisitor >>> com/sjtu/yifei/route/RouteRegister{InjectClassVisitor >>>        public *** init() {InjectClassVisitor >>>            register("com.sjtu.yifei.FBQWNfbTpY.com$$sjtu$$yifei$$FBQWNfbTpY$$RouteInject")InjectClassVisitor >>>            register("com.sjtu.yifei.klBxerzbYV.com$$sjtu$$yifei$$klBxerzbYV$$RouteInject")InjectClassVisitor >>>            register("com.sjtu.yifei.JmhcMMUhkR.com$$sjtu$$yifei$$JmhcMMUhkR$$RouteInject")InjectClassVisitor >>>            register("com.sjtu.yifei.fpyxYyTCRm.com$$sjtu$$yifei$$fpyxYyTCRm$$AInterceptorInject")InjectClassVisitor >>>        }InjectClassVisitor >>> }TransformPluginLaunch >>> ========== Transform insert cost 0.017 secs end ===========```- Routerfit.register(Class service) 这一步主要是通过动态代理模式实现接口中声明的服务。前面讲的是整体的框架设计思想,便于读者从全局的觉得来理解ARetrofit的框架的架构。接下来,将待大家个个击破上面提到的annotationProcessor、 transform在项目中如何使用,以及动态代理、拦截器功能的实现等细节。## 一、annotationProcessor生成代码annotationProcessor(注解处理器)是javac内置的一个用于编译时扫描和处理注解(Annotation)的工具。简单的说,在源代码编译阶段,通过注解处理器,我们可以获取源文件内注解(Annotation)相关内容。Android Gradle 2.2 及以上版本提供annotationProcessor的插件。在ARetrofit中annotationProcessor对应的module是auto-complier,在使用annotationProcessor之前首先需要声明好注解。关于注解不太了解或者遗忘的同学可直接参考我之前写的(https://www.jianshu.com/p/ef1146a771b5" target="_blank">Java注解这篇文章,本项目中声明的注解在auto-annotation这个module中,主要有:- @Extra 路由参数- @Flags intent flags- @Go 路由路径key- @Interceptor 声明自定义拦截器- @RequestCode 路由参数- @Route路由- @Uri- @IMethod 用于标记注册代码将插入到此方法中(transform中使用)- @Inject 用于标记需要被注入类,最近都将插入到标记了#com.sjtu.yifei.annotation.IMethod的方法中(transform中使用)创建自定义的注解处理器,具体使用方法可参考[利用注解动态生成代码](https://blog.csdn.net/Gaugamela/article/details/79694302),本项目中的注解处理器如下所示:```//这是用来注册注解处理器要处理的源代码版本。@SupportedSourceVersion(SourceVersion.RELEASE_8)//这个注解用来注册注解处理器要处理的注解类型。有效值为完全限定名(就是带所在包名和路径的类全名@SupportedAnnotationTypes({ANNOTATION_ROUTE, ANNOTATION_GO})//来注解这个处理器,可以自动生成配置信息@AutoService(Processor.class)public class IProcessor extends AbstractProcessor {    }```生成代码的关键部分在```GenerateAInterceptorInjectImpl``` 和 ```GenerateRouteInjectImpl```中,以下贴出关键代码:```public void generateAInterceptorInjectImpl(String pkName) {        try {            String name = pkName.replace(".",DECOLLATOR)   SUFFIX;            logger.info(String.format("auto generate class = %s", name));            TypeSpec.Builder builder = TypeSpec.classBuilder(name)                    .addModifiers(Modifier.PUBLIC)                    .addAnnotation(Inject.class)                    .addSuperinterface(AInterceptorInject.class);            ClassName hashMap = ClassName.get("java.util", "HashMap");            //Map
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )