ARouter参考:
https://www.jianshu.com/p/6021f3f61fa6
https://juejin.im/entry/59ef1d0c51882578da0d0ea8
组件化参考:
https://www.jianshu.com/p/1b1d77f58e84
组件化和插件化的最大区别(应该也是唯一区别)就是组件化在运行时不具备动态添加和修改组件的功能,但是插件化是可以的。
组件解耦:我们不可以直接使用compile project(:reader)这种方式来引用组件,要实现组件之间的完全解耦,我们不仅不能直接使用其他组件中的类,最好能根本不了解其中的实现细节。只有这种程度的解耦才是我们需要的。
路由使用场景:
- 动态跳转
-
组件化
最新版的ARouter已经可以支持生成路由文档了
配置:
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName(), AROUTER_GENERATE_DOC: "enable"]
}
}
什么是组件化?
组件化就是将我们的app工程分隔成若干独立的组件,每个组件可以单独运行和调试,组件之间可以使用对方提供的服务,可以相互传递数据,要做到组件可以单独运行和调试,所以就必须保证组件之间不能直接进行类引用,就是说一个组件中的类对其他组件来说是透明的,组件应该有自己的生命周期(加载、卸载、降维),可以集成调试。
如何实现?
* 单独运行和调试
1、我们知道在module的gradle文件中,如果gradle依赖的插件是apply plugin: 'com.android.library'的话是不能单独运行的,如果是apply plugin: 'com.android.application'才可以。
2、单独运行的module的AndroidManifest文件中都必须有入口Activity
如果保证一个module在开发的时候可以独立运行,在发布的时候又可以集成到主app中呢?
我们可以设置一个变量isRunAlone,标记当前是否需要单独调试,根据isRunAlone的取值,使用不同的gradle插件(library还是application)和AndroidManifest文件,甚至可以添加Application等Java文件,以便可以做一下初始化的操作。
关键词:isRunAlone变量、使用不同的gradle插件、使用不同的AndroidManifest文件、可以添加Application等Java文件如果需要做初始化操作的话。(library是没有Application的)
* 组件之间可以使用对方提供的服务
既然组件之间不能直接进行类的引用,那么如何访问其他组件中的类呢?
在这里我们采用接口+实现的方式。每个组件声明自己提供的服务Service,这些Service都是一些抽象类或者接口,组件负责将这些Service实现并注册到一个统一的路由Router中去。如果要使用某个组件的功能,只需要向Router请求这个Service的实现,具体的实现细节我们全然不关心,只要能返回我们需要的结果就可以了。这与Binder的C/S架构很相像。
1、组件怎么暴露自己提供的服务呢?在项目中我们简单起见,专门建立了一个componentservice的依赖库,里面定义了每个组件向外提供的service和一些公共model。
2、服务的具体实现是由所属组件注册到Router中的,那么是在什么时间注册的呢?这个涉及到组件的生命周期
* 组件的生命周期
我们的目标是做到对组件按需、动态的使用,所以组件要有自己的生命周期,加载、卸载和降维。
由于我们要动态的管理组件,所以给每个组件添加几个生命周期状态:加载、卸载和降维。为此我们给每个组件增加一个ApplicationLike类,里面定义了onCreate和onStop两个生命周期函数。
1、加载:上面讲了,每个组件负责将自己的服务实现注册到Router中,其具体的实现代码就写在onCreate方法中。那么主项目调用这个onCreate方法就称之为组件的加载,因为一旦onCreate方法执行完,组件就把自己的服务注册到Router里面去了,其他组件就可以直接使用这个服务了。
2、卸载:卸载与加载基本一致,所不同的就是调用ApplicationLike的onStop方法,在这个方法中每个组件将自己的服务实现从Router中取消注册。不过这种使用场景可能比较少,一般适用于一些只用一次的组件。
3、降维:降维使用的场景更为少见,比如一个组件出现了问题,我们想把这个组件从本地实现改为一个wap页。降维一般需要后台配置才生效,可以在onCreate对线上配置进行检查,如果需要降维,则把所有的UI跳转到配置的wap页上面去。
一个小的细节是,主项目负责加载组件,由于主项目和组件之间是隔离的,那么主项目如何调用组件ApplicationLike的生命周期方法呢?
a.反射
b.基于编译期字节码插入的方式(javassist)
可以用 Javassist 改变 Java 类的字节码,而无需真正了解关于字节码或者 Java 虚拟机(Java virtual machine JVM)结构的任何内容
* 集成调试
每个组件单独调试通过并不意味着集成在一起没有问题,因此在开发后期我们需要把几个组件集成到一个app里面去验证。由于我们上面的机制保证了组件之间的隔离,所以我们可以任意选择几个组件参与集成。这种按需索取的加载机制可以保证在集成调试中有很大的灵活性,并且可以加大的加快编译速度。