跳到主要内容

模块化架构

问题

Android 模块化架构如何设计?模块之间如何通信?

答案

模块化拆分策略

模块类型说明

模块类型说明示例
app壳模块,组装 Featureapp
feature-*业务功能模块feature-home, feature-login
core-*基础能力模块core-network, core-ui
common通用工具工具类、扩展函数

模块间通信

Feature 模块之间不能直接依赖,通过以下方式通信:

方式一:Navigation(推荐)

// feature-home 跳转到 feature-profile
// 使用 Deep Link,无需直接依赖
navController.navigate("app://profile/user123")

方式二:接口下沉 + DI

// core-common 中定义接口
interface UserService {
suspend fun getCurrentUser(): User
}

// feature-profile 中实现
@Singleton
class UserServiceImpl @Inject constructor(
private val userRepo: UserRepository
) : UserService {
override suspend fun getCurrentUser() = userRepo.getUser()
}

// feature-home 中通过 DI 注入接口
@HiltViewModel
class HomeViewModel @Inject constructor(
private val userService: UserService
) : ViewModel()

Gradle 配置

feature-home/build.gradle.kts
plugins {
id("com.android.library")
id("dagger.hilt.android.plugin")
}

dependencies {
implementation(project(":core-network"))
implementation(project(":core-ui"))
implementation(project(":core-common"))
// 不依赖其他 feature 模块
}
Convention Plugin

使用 Gradle Convention Plugin 统一模块配置,避免每个模块重复配置 compileSdk、minSdk 等参数:

build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.android.library")
pluginManager.apply("org.jetbrains.kotlin.android")
extensions.configure<LibraryExtension> {
compileSdk = 34
defaultConfig.minSdk = 24
}
}
}
}

常见面试问题

Q1: 模块化有什么好处?

答案

  1. 编译速度:只重新编译修改的模块,增量编译更快
  2. 代码隔离:Feature 模块互不依赖,避免耦合
  3. 团队协作:不同团队负责不同模块,减少合并冲突
  4. 动态化:可配合 Dynamic Feature 实现按需下载

Q2: 如何避免模块间循环依赖?

答案

  • 严格遵循依赖方向:app → feature → core,不允许反向依赖
  • Feature 模块之间不直接依赖,通过接口下沉到 core 层
  • 使用 Gradle 的 api / implementation 控制传递依赖范围
  • CI 中添加架构检查(如 module-graph

Q3: 模块化和组件化有什么区别?

答案

  • 模块化:按功能拆分 Gradle Module,编译隔离,关注代码组织
  • 组件化:模块化的进阶,每个组件可独立运行和调试(通过切换 com.android.application / com.android.library),关注独立运行能力

相关链接