【长篇】Android组件化细讲+手写实现
Android开发进阶必看之【组件化架构技术精讲合集】B站搜这个视频。
什么是组件化,为什么要组件化
耦合、维护、扩展、项目大了编译慢
1.png公共层:glide、第三方sdk
系统层:蓝牙、
将原本业务逻辑拆分成业务模块
2.png好处:
3.png编译速度:只编译单个模块就好了
超集解耦:以前是包名,现在每个都是application,无耦合
功能重用
便于团队:彼此只要关注自己模块,定位bug
组件化要注意的几个点:
1要注意包名和资源文件命名冲突问题
2Gradle中的版本号统一管理
3组件在Application和library之间如何做到随意切换
4AndroidManifest.xml文件的区别
5Library不能在Gradle文件中有applicationId
Gradle中的版本号统一管理
第一种方式,定义在gradle.properties里变量(手册)
第二种方式,定义在build.gradle里类似json方式;
第三种方式,自己创建一个gradle,在主gradle去加载,跟第二种意思差不多
以下是第一种方式:
4.png第三种:
36.png
所有定义在gradle.properties里变量都是String类型的,使用时要转int
使用时:
5.png组件在Application和library之间如何做到随意切换
定义的这个变量起作用
6.png 7.pngAndroidManifest.xml文件的区别
8.png如何在不同的需求下加载不同的manifest呢?
每个组件都新建文件夹、copy,建立符合lib的manifest:
9.png然后在每个相对应组件的build.gradle里加上如下代码,就可动态切换:
10.pngLibrary不能在Gradle文件中有applicationId
此点容易被忽略
11.png主Application不用修改applicationId、lib切换等(因为一直会是App)
37.png最后在主Application中:
12.png当然还有些细节点,比如
13.png也要跟着版本号变化而变化。
14.png 15.pngAPT技术实现手写ARouter框架
组件化开发中路由框架究竟是什么
各个组件虽然划分好了,但是组件间的跳转、通信问题需要解决。没有任何耦合,彼此之间联系不上。
16.png路由框架就是解决这个问题。彼此没有任何依赖的模块又能得到其他Activity。
思路:App一启动的时候,就在Applicaiton里将所有的Activity Class对象(并不是具体实例)装到一个容器里,其他模块要用时,直接去这个容器里拿。
创建一个lib 名字叫arouter,并创建ARouter类
17.png之后每隔模块都implement arouter模块
18.png现在map里还没有数据,需要放进来。
思路:每隔模块创建一个额工具类,把activity加进来。为了更加规范,在arouter下定义IRouter接口:
login模块工具类举例(下面的注解处理器实际上就是在每个模块中动态生成这里面的代码):
20.png然后调用就可以了。
但是不合理:1每个都要创建、2每次添加新的activity,管理时容易忘记修改这里。需要花心思管理。
通过注解扫描解决!!!
Android编译时注解---APT技术
APT(Annotation Processing Tool)
即注解解释器,是一种处理注解的工具,确切说他是javac的一个工具,用来在编译时扫描和处理注解。
简单来说就是在应用处于编译期的时候,通过注解处理器解析注解生成文件。
我们用编译时技术去动态生成Util类
创建注解和注解处理器
创建两个java library(不是Android library,因为注解和注解处理器都是java概念)
22.png然后让每个模块都去依赖这两个库。
23.png注解处理器要用annotationProcessor
编译时,读取到这段回去找注解处理器执行代码
注解的作用就是标记需要加入到map里面的类。
在annotation下创建一个BindPath注解:
24.png在activity里添加我们的注解,参数就是key
25.png注解有了,然后再写我们的注解处理器
自定义一个AnnotationCompiler类
1,继承AbstractProcessor类,实现process()方法
2,将我们的类注册成注解处理器(加上一个标记注解就行了):在build中先导入谷歌service库,然后在类上添加库中注解@AutoService(Processor.class)
完成上面两步,我们定义的注解处理器才会在编译时找到。
接下来填补我们的注解处理器类:
注解处理器要重写方法来声明哪些注解需要被这个处理器识别,所以先添加下依赖:
28.png要重写4个方法,前三个都是准备工作,最后的process是核心处理部分:
1init():创建filer文件
2getSuppertedSourceVersion() :支持的java版本
3getSupportedAnnotationTypes():声明要识别的注解
4process():处理注解
注解处理器能得到被BindPath所标记的内容
30.png最后编译一下,或者添加一个login2 activity
29.png动态生成了我们之前写的Utils里的代码。
其他模块的Activity添加上我们的BinderPath注解即可
Ctrl+n
编译后,每个模块都动态生成了Utils类。
工具类现在生成好了,但里面的方法还没有执行。
我们在Arouter下添加方法:
通过包名获取这个包下面所有的类名
然后在初始化时:
33.png方法就会被调用了。
然后ARouter的init是在Application里执行的,创建MyApplication,初始化ARouter。
34.png别忘了在Manifest里修改。
接下来运行即可
35.png一个第三方库,每个模块都要添加一次的话(比如30个),工程量很大。可以通过gradle 遍历数组
组件间通信
(待续...)