构建模块化工程
该工程使用的gradle版本为7.4.0,使用的gradle插件是7.3.0,kotlin插件版本为1.7.10,每个模块都有简单的说明,有需要的可以看一下。
模块化工程目录
工程一共分为六个模块
- app模块为壳工程,主要负责APP其他模块集成,签名,主题配置,app logo, 渠道配置
- businessModelOne是你的业务模块,你可以随时删除(在测试中该业务模块将会提供服务给其他模块使用,该模块中的Activity 将会作为APP首页)
- businessModelTwo是业务模块,也可以删除(在测试中这个模块将会使用businessModelOne中提供的服务)
- common模块主要负责一些基础第三方的集成和封装,如网络,数据库,日志,路由等,为了更好的分离,commom不应该存放具体的业务代码,所以需要出现pub_mod模块存放,共有的业务逻辑
- pub_mod公有资源,逻辑模块用于个别模块建的资源,javabean, 逻辑共享比如,登陆界面需要用到User这个数据类,个人中心界面也需要使用的这个数据类,则将这个类放入该包中比如一些多个模块使用到的工具类,都会放到这个模块下
- pub_service暴露模块的服务,比如登陆模块有功能会验证是否已经登陆,在其他模块也需要使用该逻辑,但是别的模块不应该依赖login模块,而应该依赖该服务模块.
第三方依赖的统一管理
在项目中,我们使用dependencies.gradle来管理整个项目所有的依赖版本,代码如下
//config.gradle,ext:添加额外的属性
ext {
//基础构建属性
android = [
compileSdkVersion : 32, // 编译sdk版本
buildToolsVersion :"30.0.1", //指定SDK构建工具的命令行版本,这个属性是可选的
applicationId :'com.td.moduleproject', //唯一标识要发布的包。
minSdkVersion : 21, //最低安装版本
targetSdkVersion : 32, //目标适配版本
versionCode : 1,
versionName : "1.0.0",
//ndkVersion : "21.0.6113669" //ndk版本配置
]
//远程依赖版本
dependent_Version = [
arouter_compiler: "1.5.2",
appcompat_version: "1.5.1",
material_version:"1.6.1",
arout_version:"1.5.2",
]
//远程依赖
dependencies = [
"appcompat" : "androidx.appcompat:appcompat:${dependent_Version["appcompat_version"]}",
"material" : "com.google.android.material:material:${dependent_Version["material_version"]}",
"arout" : "com.alibaba:arouter-api:${dependent_Version["arout_version"]}",//路由
"arouter_compiler" : "com.alibaba:arouter-compiler:${dependent_Version["arouter_compiler"]}",//路由解释器
"core_ktx" : 'androidx.core:core-ktx:1.7.0',
"junit" :'junit:junit:4.13.2',
"ext_junit" :'androidx.test.ext:junit:1.1.3',
"espresso_core" :'androidx.test.espresso:espresso-core:3.4.0',
"retrofit" :'com.squareup.retrofit2:retrofit:2.9.0'
]
//签名配置
sign=[
keyAlias :'admin',
keyPassword :'admin',
storeFile :"/Users/Project/admin.keystore",
storePassword: 'admin',
]
}
之后在工程的build.gradle中引用该文件
之后在各个模块中的依赖我们只需要引用dependencies.gradle中的变量就可以,具体的版本号将在dependencies.gradle得到统一的管理
dependencies {
//使用api替代implementation,这样应用common模块的模块都能使用common模块下引用的其他三方库,避免公用的第三方需要在别的地方引用
implementation rootProject.ext.dependencies["core_ktx"]
api rootProject.ext.dependencies["appcompat"]
//implementation buildDep["arout"]
//implementation 'com.google.android.material:material:1.6.1'
api rootProject.ext.dependencies["material"]
//引用jar包
api files('libs/AMap_Location_V5.5.1_20211008.jar')
//引用aar包
implementation(fileTree("libs"))
testApi rootProject.ext.dependencies["junit"]
androidTestApi rootProject.ext.dependencies["ext_junit"]
androidTestApi rootProject.ext.dependencies["espresso_core"]
api rootProject.ext.dependencies["arout"]
kapt rootProject.ext.dependencies["arouter_compiler"]
api rootProject.ext.dependencies["retrofit"]
}
common模块引用的第三方
对于common模块来说,他是整个项目的第三方库的管理者,我们所有的模块都会集成common。对于common中编写的非业务性代码我们可以直接引用。但是如果common中引用的其他第三方,我们却没办法使用,这时候就需要将implementation
改为api
这会改变引用包的可见性,让引用common模块的其他模块也能使用common中引用的第三方。
模块间的逻辑共享
想象一下这个场景,如果我们的下单模块需要去验证是否登陆,而登陆的业务是在登陆模块中的。
这时最简单的方法是让下单模块导入登陆模块,但这样会因为业务的耦合而导致代码的耦合。ARouter
为我们提供了模块间服务的暴露方法。
ARouter
在上面的代码中
- bussinessModelOne模块是服务的提供者,它实现了服务的具体细节
- businessModelTwo模块是服务的消费者,他调用了服务
- pub_service是服务的接口,这样可以避免让两个业务模块相互依赖,他们只需要都依赖这个pub_service这个模块就能够实现服务的调用
- 这个接口的隔离是java中的ISP,不过ARouter帮我们做的更简单了
pub_service提供了服务的接口
import com.alibaba.android.arouter.facade.template.IProvider
interface PubService : IProvider {
fun getRandom(base : String) : String
}
businessmodelOne 提供了两个服务
@Route(path = "/BussinessOneService/pubService", name = "pubService")
class PubServiceImp : PubService {
override fun getRandom(base: String): String {
return "PubServiceImp${Random().nextDouble().toString() + base}"
}
override fun init(context: Context?) {
}
}
@Route(path = "/BussinessOneService/pubService2", name = "pubService2")
class PubServiceImp2 : PubService {
override fun getRandom(base: String): String {
return "2PubServiceImp${Random().nextDouble().toString() + base}"
}
override fun init(context: Context?) {
}
}
businessModelTwo 服务的调用者
@Route(path = "/businessModelTwo/bussinessTwoActivity")
class BusinessModelActivity : AppCompatActivity() {
//通过Arouter的注入服务
@Autowired(name = "/BussinessOneService/pubService")
lateinit var pubService: PubService
@Autowired(name = "/BussinessOneService/pubService2")
lateinit var pubService2: PubService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ARouter.getInstance().inject(this)
val binding = BusinessmodeltwoMainActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.pubText1.text = pubService.getRandom("pubText1")
binding.pubText2.text = pubService2.getRandom("pubService2")
}
}
以上,就是模块化工程的构建。