项目架构,从来都是按照实际需求情况演进的
<壹> app模块
在组件化/模块化架构中,app 模块作为宿主(主壳)是非常关键的设计。它的作用远远不止是一个简单的启动入口,而是一个精心设计的架构核心。让我详细解释它的作用和用意:
一、核心作用
1. 应用的统一入口
kotlin
// app/build.gradle
apply plugin: 'com.android.application'
- 这是唯一拥有
application插件的模块 - 包含应用的
Application类和启动Activity - 定义了应用的包名、版本号、签名等元信息
2. 组件/模块的装配中心
kotlin
// app/build.gradle
dependencies {
implementation project(':core')
implementation project(':feature-ui')
implementation project(':feature-arch')
implementation project(':feature-performance')
// ... 按需集成其他模块
}
- 像一个"主板",把所有功能模块像"插卡"一样集成在一起
- 决定哪些模块被包含在最终APK中
3. 全局配置和管理
kotlin
// app/src/main/java/com/example/MyApplication.kt
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// 全局初始化
initRouter() // 路由框架初始化
initCrashHandler() // 全局异常处理
initPerformance() // 性能监控初始化
initLogging() // 日志系统初始化
// 按需延迟初始化某些模块
initModulesLazily()
}
}
4. 路由和导航中枢
ARouter在单activity多compose的场景,不适用。
TheRouter未确定。
kotlin
// app模块负责配置全局导航,或者
object AppRouter {
fun setup() {
ARouter.init(application)
ARouter.openDebug()
// 添加全局拦截器(如登录检查)
ARouter.getInstance().addInterceptor(LoginInterceptor())
}
}
// 壳中的MainActivity通常作为容器
class MainActivity : BaseActivity() {
// 可能只是一个简单的容器,实际内容由各模块提供
}
二、架构用意
1. 单一职责原则
- 各业务模块:专注于自己的功能实现,不关心如何被集成
- 宿主模块:专注于组装和调度,不包含具体业务逻辑
2. 解耦的关键设计
text
传统单体应用:
app(包含所有代码和逻辑)
|
├── ui包
├── network包
├── database包
└── ...
组件化架构:
app(空壳,仅集成和调度)
|
├── core(基础库)
├── feature-A(独立业务组件,可单独运行)
├── feature-B(独立业务组件,可单独运行)
└── ...
- 业务模块之间没有直接依赖,都只依赖
core模块 - 模块间通信通过接口/路由,而不是直接引用
3. 灵活的动态配置
groovy
// 可以灵活控制哪些模块被包含
dependencies {
// 基础模块,始终包含
implementation project(':core')
// 按需引入的特性模块
if (isFeatureEnabled('performance')) {
implementation project(':feature-performance')
}
if (isFeatureEnabled('custom_ui')) {
implementation project(':feature-ui')
}
// 调试专用模块,只包含在debug版本
debugImplementation project(':debug-tools')
}
4. 独立调试与集成发布的切换
groovy
// 在业务模块中,可以这样配置
// feature-ui/build.gradle
if (isRunAlone()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
android {
defaultConfig {
if (isRunAlone()) {
// 独立运行时需要自己的ApplicationId
applicationId "com.example.feature.ui"
}
}
sourceSets {
main {
// 独立运行时使用自己的AndroidManifest
if (isRunAlone()) {
manifest.srcFile 'src/main/runAlone/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
}