在上一篇文章《组件化实践详解(一)》中咱们介绍了组件化实践的目标和实践步骤,本文继续说说关于组件化实践遇到的问题及思考。android
这条原本我是不想写的,可是不少组件化的文章里都会费尽心思的写组件内的架构设计。bash
那我也谈一谈个人见解:首先回归初心,想一想组件化的目的,为了各个业务组件能够单独运行。划重点:目的是单独运行,把以前在App Module的代码挪到本身单独的Module,而后可以独立运行;而不是大面积重构!!我也相信对于大部分团队,实际上并无不少的时间去作重构,尤为是在作组件化的过程当中同时大面积重构,肯定作了风险评估吗?微信
对于组件化的总体设计,须要遵循制定的规则,可是对于组件内的架构设计,实际上不须要特殊的要求,代码你爱怎么写就能够怎么写,无论你使用MVC、MVP仍是MVVM,根据各自状况合理选择就行了。这个话题原本就不属于组件化项目的范畴。网络
假如以前的几步咱们都顺利完成,如今整个Project已经变成了下图整个样子。架构
那咱们的Module要怎么才能跑起来呢?app
两者结合呢?借助冯大大在MDCC上的分享,将Module分为两个模式:Release模式和Debug模式,Release模式下做为Library,供宿主依赖;而在Debug模式下则做为Application工程,本身单独运行。框架
build.gradle中根据gradle中的一个属性值来判断处于哪一种模式下:maven
if (isDebug.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
sourceSets {
main {
if (isDebug.toBoolean()) {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/release/AndroidManifest.xml'
}
}
}
复制代码
在Release中的AndroidManifest配置默认启动的主Activity。组件化
这样一来调试的问题也就解决了。可是实际上这仅仅是一个Demo雏形,咱们思考几个带出来的问题:gradle
如何对这个状况作优化:各个独立Module提供稳定版本的aar!
如下介绍些关于工程化的经验
部分业务组件必定会遇到依赖一些三方组件须要提早初始化的状况,正常咱们的作法都是在应用的Application中作的。此时咱们在独立的Module开发,没有了应用的Application,那么能够本身建立一个Module的Application,如下提几种实现的思考:
备注:而怎么判断调用业务Module呢?两个场景:UI跳转或者方法调用,这两种判断可使用路由框架来协助。
Tinker做为热修复的可靠解决方案,想必不少App都会集成,可是Tinker集成稍繁琐的地方就在于:为了确保Application也能修复,须要改造Application,改造完成以后打的包出来真正的Application已经被修改,而写上了咱们逻辑的Application实际上变成了一个普通类,只是相应方法被真正的Application调用!
那我想把Tinker这个模块也单独做为一个Module来使用,能行吗?首先来思考一个问题:Application要在哪里,Library中仍是Host?
答案是Library中,由于各个Module中可能会存在不方便获取Context的场景,解决方案之一就是使用Application的Context。假设Application放在Host中,那Module确定是没法使用的。固然刚刚咱们说到Module本身的Application,可是别忘了若是Module没有呢?
把Application放到Library中也不是说移就能移:
面对如此抉择,那究竟是移仍是不移?一个好方法是原来Host的Application只作较小改动:并不移出来以前的各类逻辑和组件,而是做为一个普通类,在Library中的Application方法执行时去回调相应Host Application的方法;随后在组件化的过程当中逐渐的移出来这些业务和组件。这样的改动成本最小又知足了当下的须要。
在拆分出来多个Module或者新建Module进行开发,新建资源的时候可能会有命名的冲突,对Gradle熟悉的同窗可能会表示使用resourcePrefix来进行限定,可是坦白说效果通常,却是不如在编码规范中加上一条以相应Module的标示做为命名的前缀。
ButterKnife——相信不少同窗都用过,这是一个注解框架,通常在绑定View的时候使用,减小了不少无心义的代码。在正常开发中咱们用起来也是6的飞起!然而当ButterKnife跑在Library工程中的时候各类Build失败就出现了:缘由在于Android Library中的R文件字段并非常量,Module在Debug模式下是Application工程能够开心玩耍,等真正集成的时候切换回Release模式就呵呵哒了。
在ButterKnife8.0以后也支持了在Library中使用,解决方式就是同时生成了一个R2,这个就是常量,于是能够在Library工程中使用。
推荐使用Android ButterKnife Plugin Plus插件,方便的一键生成而后将R更改成R2;或者本身仿照去写一个AS插件,直接生成R2。
备注:同时注意R2只能使用在注解中,于是点击事件要写成这样:
@OnClick(R2.id.tv_back_selerole)
public void onClick(View view) {
if (view.getId() == R.id.tv_back_selerole) {
dealBack();
}
}
复制代码
这个问题的引出是在组件化相对成熟的阶段,已经初步完成了咱们的预期目标,可是细化的过程当中逐渐意识到一个问题:Library库愈来愈大,其实单独的一个Module并不会须要那么多的组件,可是单独Module运行的时候仍是被引用上了,也会拖慢单独Module的执行速度。
因而咱们提出了另一个名词:去中心化。将基础库进行细粒度的拆分,将开发中必定会用到的例如网络请求、EventBus、公共类等放在了Library中,而将别的不经常使用三方组件如地图等移出去,只供须要的Module去依赖,而普通的Module则只依赖经常使用的Library。
这样能够有效的避免Library逐渐变得膨胀,也给各Module只去依赖本身须要的特定Library能力。
历经千辛万苦咱们对项目作了组件化实践,那究竟收获了哪些好处呢?
今日头条各Android客户端团队招人火爆进行中,各个级别和应届实习生都须要,业务增加快、日活高、挑战大、待遇给力,各位大佬走过路过千万不要错过!
本科以上学历、非频繁跳槽(如两年两跳),欢迎加个人微信详聊:KOBE8242011