每当开始做一个新的APP , 都是喜忧参半 。喜得是对新的APP充满期待,希望小成就感。忧的是没有一款好的开发框架 ,最后发展成传说中“烂尾楼” 。今儿个看到一片博客感觉写的思路清晰,言简意赅,很实用,特来做一下记录 。大部分摘自原文章 。
感谢原创作者 https://blog.csdn.net/guiying712/article/details/55213884 ;
一、为什么要组件化 ,对比一下两张图来说
图一展示没有组件化的架构 ,全部业务包都写在主工程App中 ,业务包之间通过文件夹来区分 ,随着业务包越来越多 ,暴露问题也会越来越多 ,业务包你中有我,我中有你 耦合性高,编译耗
1、实际业务变化非常快,但是单一工程的业务模块耦合度太高,牵一发而动全身;
2、对工程所做的任何修改都必须要编译整个工程;
3、功能测试和系统测试每次都要进行;
4、团队协同开发存在较多的冲突.不得不花费更多的时间去沟通和协调,并且在开发过程中,任何一位成员没办法专注于自己的功能点,影响开发效率;
5、不能灵活的对业务模块进行配置和组装;
为了满足各个业务模块的迭代而彼此不受影响,更好的解决上面这种让人头疼的依赖关系,就需要整改App的架构。
上图是组件化工程模型,为方便理解这张架构图,下面列举一些组件化工程中用到的名词的含义:
总的来说 ,App的组件化是告别结构臃肿,降低耦合 ,让业务模块变成独立开发模块 。如果要分离可以随时打成"arr"包依赖到app壳下边 。在集成模式下,这些业务模块是library 。开发的时候(组件模式下)变成application,这个在gradle.builder配置文件下通过变量来控制 。
二、具体方案: 组件模式和集成模式的转换
Android Studio中的Module主要有两种属性,分别为:
1、application属性,可以独立运行的Android程序,也就是我们的APP;(集成模式下)
2.library属性,不可以独立运行,一般是Android程序依赖的库文件;(组件开发模式下)
不能每次集成和组件开发区手动更改applicaton和library吧 ,要一处改变,处处生效 ,设置java静态变量不正好可以实现嘛。每当生成一个项目 ,androidstudio的根目录会自动生成gradle.properties文件 ,而项目中不管是moudle还是app壳任何一个build.gradle都可以去读取gradle.properties中配置的常量 ,gradle.properties只能定义字符串类型 。设置如下
在moudle中设置如下 : 字符串转boolean
这样就解决了独立开发和集成的问题 。
三、集成模式和组件模式下的 AndroidManifest.xml的合并问题
因为在组件模式下开发 ,每一个moudle配置着自己的注册清单文件 ,导致各自有各自的启动Activity ,等等一些配置,这样在集成模式的时候,各模块之间会起冲突,手动改太麻烦 。其实注册清单文件是可以指定文件夹的 ,如下图
这样就解决了这个问题 。
四、全局Application问题
每一个模块可能或多或少都会用到Application全局变量 ,如果每一个模块都去创建Appication ,那么在集成模式的时候就会起冲突(不允许出现多个Application) ,怎么解决呢,这就涉及到一个公用的模块Common组件,在这个模块中可以封装2个以上模块都用到的base类,其中就包括BaseApplication 类 。Common组件顾名思义就是公用的模块。所以每一个业务模块都要去依赖Common组件 ,在App启动时候,BaseApplication会被初始化 。另外也可以初始化一些第三方库。在组件话开发模式下会涉及到需要保存登陆返回的token,否则后续模块接口无法请求。这样就可以在Application中模拟写登陆接口在跳转到各自模块。
五、Library的依赖问题
假如A组件依赖了Conmon ,和多媒体第三方组件 ,而Common和多媒体组件都依赖了日志组件 ,那么问题来了,日志组件会被重复依赖吗,答案是不会 ,在build文件下可以看到,编译打包的时候,这些组件都被打包成了arr包 ,然后被壳工程依赖 ,在构建过程中Gradle会自动派出重复的组件arr包。另外常见的第三方库中可能存在v4,v7这种包,而我们的common中也会存在这种包导致多包重复加载 ,解决办法 踢除重复的包 ,例如踢除V4包
六、组件之间的调用和通信
这里我将介绍开源库的“ARouter” ,有兴趣的同学情直接去ARouter的Github主页学习:ARouter,楼主需要再总结一下,这里先不多说了 。
如果组件之间需要传递消息,可以通过广播的形式 ,也可以通过Eventbus来实现。 待补充
七、组件之间的资源文件名字冲突
这种情况不可避免,目前没有什么好的方法,只能说大家做好协商,后续友好的方法会补上 。当然如果在组件的build.gradle添加如下的代码:
但是设置了这个属性后有个问题,所有的资源名必须以指定的字符串做前缀,否则会报错,而且resourcePrefix这个值只能限定xml里面的资源,并不能限定图片资源
八、简介App壳的配置
主要就是release和debug中的配置 ,mimsdk和targetsdk版本的配置统一 。dependencies中配置isMoudle变量组件开发模式下和集成模式下的依赖项。
九、总结一下业务组件和Main组件之间 。
业务组件就是根据业务逻辑的不同拆分出来的组件,业务组件的特征如下:
1、业务组件中要有两张AndroidManifest.xml,分别对应组件开发模式和集成开发模式,这两张表的区别请查看 组件之间AndroidManifest合并问题 小节。 查看第三小节
2、业务组件在集成模式下是不能有自己的Application的,但在组件开发模式下又必须实现自己的Application并且要继承自Common组件的BaseApplication,并且这个Application不能被业务组件中的代码引用,因为它的功能就是为了使业务组件从BaseApplication中获取的全局Context生效,还有初始化数据之用。 查看第四小节
3、业务组件有debug文件夹,这个文件夹在集成模式下会从业务组件的代码中排除掉,所以debug文件夹中的类不能被业务组件强引用,例如组件模式下的 Application 就是置于这个文件夹中,还有组件模式下开发给目标 Activity 传递参数的用的 launch Activity 也应该置于 debug 文件夹中; 查看下图12
4、业务组件必须在自己的 Java文件夹中创建业务组件声明类,以使 app壳工程 中的 应用Application能够引用,实现组件跳转,具体请查看 组件之间调用和通信 小节; 查看 ARouter路由的使用
5、业务组件必须在自己的 build.gradle 中根据 isModule 值的不同改变自己的属性,在组件模式下是:com.android.application,而在集成模式下com.android.library;同时还需要在build.gradle配置资源文件,如 指定不同开发模式下的AndroidManifest.xml文件路径,排除debug文件夹等;业务组件还必须在dependencies中依赖Common组件,并且引入ActivityRouter的注解处理器annotationProcessor,以及依赖其他用到的功能组件。查看第二小节
下边是业务组件的配置 ,在sourceSet中过滤掉集成模式下所有debug文件 ,主要是在组件开发模式下,要设置当前的组件Application和lunchActivity在debug文件夹下 ,继承Common组件下的Application ,实现调用全局的Context .如上边3所说
debug目录如下图 :
十、组件化项目的混淆方案
组件化项目的Java代码混淆方案采用在集成模式下集中在app壳工程中混淆,各个业务组件不配置混淆文件。集成开发模式下在app壳工程中build.gradle文件的release构建类型中开启混淆属性,其他buildTypes配置方案跟普通项目保持一致,Java混淆配置文件也放置在app壳工程中,各个业务组件的混淆配置规则都应该在app壳工程中的混淆配置文件中添加和修改。
之所以不采用在每个业务组件中开启混淆的方案,是因为 组件在集成模式下都被 Gradle 构建成了 release 类型的arr包,一旦业务组件的代码被混淆,而这时候代码中又出现了bug,将很难根据日志找出导致bug的原因;另外每个业务组件中都保留一份混淆配置文件非常不便于修改和管理,这也是不推荐在业务组件的 build.gradle 文件中配置 buildTypes (构建类型)的原因。
十一、组件化工程的gradle.properties文件
在组件化实施流程中我们了解到gradle.properties有两个属性对我们非常有用:
1、在Android项目中的任何一个build.gradle文件中都可以把gradle.properties中的常量读取出来,不管这个build.gradle是组件的还是整个项目工程的build.gradle;
2、gradle.properties中的数据类型都是String类型,使用其他数据类型需要自行转换;
为了解决上面问题就必须将Android项目中 build.gradle 中的 buildToolsVersion 和 GradleBuildTools 版本号从线上代码隔离出来,保证线上代码的 buildToolsVersion 和 Gradle Build Tools 版本号不会被人为改变。
AndroidStudio本地化配置gradle的buildToolsVersion和gradleBuildTools
后续补充demo 。
总结 :知识无价 ,再次感谢原创作者。
组件化相比于单一工程优势是显而易见的:
1.组件模式下可以加快编译速度,提高开发效率;
2.自由选择开发框架(MVC /MVP / MVVM /);
3.方便做单元测试; 待补充
4.代码架构更加清晰,降低项目的维护难度;
5.适合于团队开发;