背景:
一个APP的组成通常会划分成多个功能模块开发,在开发的过程中会尽可能的保证单模块的独立性降低相互之间的耦合度。尤其是B2B平台的定制化模式,客户的需求总是多种多样的甚至奇葩的。比如A客户只要模块1、模块3的功能,B用户只要模块2、模块4的功能…… 怎么满足客户的需求?怎么以一个攻城狮的身份给客户优质化的服务?
有朋友会说你真是杞人忧天,提这么一个白痴的问题。所有的代码都在工程里面,他要什么功能你在页面就显示什么,不要的就隐藏界面不就实现了嘛。这种方式速率确实很快能完成任务,达到了满足客户的需求目标。优质化服务的概念是什么?一个APP如果是100M大小由四个模块组成,模块1-10M、模块2-20M、模块3-30M、模块4-40M,那么A用户按照上面的解决方式APP就是完整的100M,可是A用户的实际需求只有模块1和模块3加起来是40M,有没有方法根据实际业务需求发布APP呢?下面说说我个人的探索。
解决方案:
实现原理是在我上篇gradle神器~Android多渠道配置管理之构建多渠道module工程分支(5)
的基础上进一步的规范化工程、模块包名、类名、资源文件的命名规则,然后配合gradle的脚本实现定制化的业务需求,模块之间的耦合性可以采用的有广播、隐式启动、EventBus、反射,更多的模块交互个人还在摸索中,就以咱们常见的底部导航做个简单的示例
假设一个APP有hello和nihao两个功能模块,现在有A和B两个客户,A的需求是只需要hello模块,B的需求是只需要nihao模块,按照构建多分支的原理在mobile分支中模块显示选择使用Fragment、模块间的耦合我选择利用反射,在main中存放Fragment的容器Activity。
1.创建渠道配置文件channel.json
[ { "channel_name" : "nihao", "versionCode" : 1, "versionName" : "1.0" }, { "channel_name" : "hello", "versionCode" : 2, "versionName" : "2.0" } ]
2.在app/build.gradle配置渠道列表
productFlavors { def json = file("${projectDir.path}/channel.json").getText("UTF-8")//读取app目录下的channel.json文件内容 def flavors = new JsonSlurper().parseText(json) //转换成Jsons数组对象 flavors.each { flavor -> "${flavor.channel_name}"{//渠道名称,对应文件中的channel_name versionCode flavor.versionCode //渠道版本号,对应文件中的versionCode versionName flavor.versionName //渠道版本名称,对应文件中的versionName } } }
3.在moblie分支创建模块包、类文件,我个人为了演示方便包名以渠道名称结束,每个包下面只有一个继承了v4的Fragmemt,
在main主目录中只有一个Activity布局是一个FrameLayout
4.根据业务需求配置sourceSets,示例的需求是A客户对应hello B客户对应nihao
/*渠道对应的资源文件*/ sourceSets { getProductFlavors().each { f -> def terminal = 'moblie' "${f.name}"{ manifest.srcFile "src/${terminal}/AndroidManifest.xml" /*该源目录包含了此源集的所有Java源文件,默认值[name/java]*/ java{ srcDir "src/${terminal}/java" if(f.name == "hello") exclude "**/nihao" else if(f.name == "nihao") exclude "**/hello" } /*该源目录包含了此源集的资源文件,默认值[name/resources]*/ resources.srcDirs = ["src/${terminal}"] renderscript.srcDirs = ["src/${terminal}"] res.srcDirs = ["src/${terminal}/res"] assets.srcDirs = ["src/${terminal}"] jniLibs.srcDirs = ["src/${terminal}"] } } }
实现的重点就是红色代码部分,exclude的意思就是不包含、排除的意思,执行gradlew assembleRelease打包命令看效果;
解压缩以后用classes-dex2jar.jar查看编译后的源码文件,已经实现了针对性的业务需求,页面效果如下: