2024年已经过半,作为一名聋人独立开发者,我常常反思这半年的进步与收获。在这篇文章中,我将分享如何使用 Jetpack Compose、Material3 结合 MVVM 架构设计一个模块化的Android应用。无论你是新手开发者,还是有经验的安卓开发人员,相信这篇文章都会对你有所帮助。
一、为什么需要模块化架构?
模块化设计的好处是:
可扩展性:各模块独立开发,彼此依赖最小化,方便新功能的添加和扩展。
- 代码复用:通用组件可以封装成独立模块,方便在项目中复用。
- 提高开发效率:不同团队可以并行开发各自负责的模块,减少相互依赖。
- 易维护:当某个模块出现问题时,定位和修复很方便。
二、模块化架构
几个模块划分:
- UI 层:负责界面的渲染和用户交互的逻辑。
- 数据层:处理数据的获取、存储及管理,和数据库和 API 交互。
- 业务逻辑层 (ViewModel):连接 UI 和数据层,处理应用的业务逻辑和状态管理。
文章会用 MVVM 架构的方式来讲解。
三、项目结构
3.1 基础项目结构
按照如下结构进行模块化设计
代码语言:java复制com.nim.app/
│
├── data/ # 数据层
│ ├── repository/ # 数据库、网络请求相关逻辑
│ ├── model/ # 数据模型
│ └── database/ # Room数据库及DAO定义
│
├── ui/ # UI 层
│ ├── theme/ # Material3 主题定义
│ ├── component/ # 通用的UI组件
│ └── screen/ # 各个页面的定义,如HomeScreen等
│
├── viewmodel/ # 业务逻辑层 (ViewModel)
│ └── WishViewModel.kt # 状态管理与业务逻辑
│
└── MainApplication.kt # 应用程序入口
四、各模块功能介绍
4.1 数据层
data/repository: 数据仓库模式 (Repository Pattern) 用于统一管理数据,负责从本地数据库或远程 API 获取数据。
代码语言:java复制class WishRepository(private val wishDao: WishDao) {
// 从数据库获取全部Wish
fun getWishes(): Flow<List<Wish>> = wishDao.getAllWishes()
// 根据ID获取单个Wish
fun getAWishById(id: Long): Flow<Wish> {
return wishDao.getAWishById(id)
}
// add
suspend fun addWish(wish: Wish) {
wishDao.addAWish(wish)
}
// update
suspend fun updateWish(wish: Wish) {
wishDao.updateAWish(wish)
}
// delete
suspend fun deleteWish(wish: Wish) {
wishDao.deleteAWish(wish)
}
}
data/model: 数据模型用于定义数据库中的表结构或者网络请求的返回结果,结合 Room
持久化数据。
@Entity(tableName = "nim_wish_table")
data class Wish(
@PrimaryKey(autoGenerate = true) val id: Long = 0L,
@ColumnInfo(name = "wish_title") val title: String = "",
@ColumnInfo(name = "wish_desc") val description: String = ""
)
4.2 业务逻辑层 (ViewModel)
viewmodel/WishViewModel: ViewModel
负责管理 UI 层和数据层的交互,处理 UI 层的状态。
class WishViewModel(private val repository: WishRepository) : ViewModel() {
val wishes: LiveData<List<Wish>> = repository.getWishes().asLiveData()
fun addWish(wish: Wish) {
viewModelScope.launch {
repository.addWish(wish)
}
}
fun deleteWish(wish: Wish) {
viewModelScope.launch {
repository.deleteWish(wish)
}
}
}
ViewModel
负责管理界面上的数据,用 LiveData
或 Flow
来更新数据,这样界面就能自动刷新了。
4.3 UI 层
ui/theme: theme
模块负责App的整体 UI 风格定义,如颜色、排版等。
@Composable
fun MyAppTheme(content: @Composable () -> Unit) {
MaterialTheme(
colorScheme = lightColorScheme(
primary = Color(0xFF6200EE),
secondary = Color(0xFF03DAC5)
),
typography = Typography(),
content = content
)
}
ui/component: 通用组件模块,用于定义项目中可复用的 UI 组件,如按钮、输入框等。
代码语言:java复制@Composable
fun MyCustomButton(onClick: () -> Unit) {
Button(onClick = onClick) {
Text(text = "Click Me")
}
}
ui/screen: screen
模块负责页面的具体实现,比如主页、详情页等。在每个页面中,通过 ViewModel 获取数据,渲染相应的 UI。
@Composable
fun HomeScreen(viewModel: WishViewModel) {
val wishes by viewModel.wishes.observeAsState(initial = emptyList())
LazyColumn {
items(wishes) { wish ->
Text(text = wish.title)
}
}
}
五、页面间导航的实现
提供了内置的导航组件管理页面间的跳转。导航逻辑放置在 MainScreen
中。
@Composable
fun MainScreen() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("detail/{id}") { backStackEntry ->
val id = backStackEntry.arguments?.getString("id")
DetailScreen(navController, id)
}
}
}
通过 NavController
可以轻松管理页面之间的跳转,保证页面之间的解耦。
六、状态管理和数据流
状态是驱动 UI 更新的核心,通过 State
或 LiveData
,可以让 UI 层随着数据变化而自动重绘。
@Composable
fun WishItem(viewModel: WishViewModel, wish: Wish) {
var isLiked by remember { mutableStateOf(false) }
Column {
Text(text = wish.title)
IconButton(onClick = { isLiked = !isLiked }) {
Icon(imageVector = Icons.Default.Favorite, tint = if (isLiked) Color.Red else Color.Gray)
}
}
}
isLiked
状态取决于图标的颜色变化,会根据状态变化自动更新界面。
七、总结
本文章讲解了清晰理解数据层、业务逻辑层和 UI 层分离。这种架构提高了开发效率,还方便了日后功能的扩展和维护。
7.1数据层
负责处理所有和数据相关的操作,如网络请求、数据库操作等。
7.2业务逻辑层 (ViewModel)
负责处理 UI 和数据之间的交互,管理 UI 状态。
7.3 UI 层
负责页面的渲染和用户交互,用 Compose
和 Material3
提供的组件构建美观 UI。
在开发时,把东西分开来做,能让应用更容易维护和升级,这种模块化的方法很不错。
有任何问题欢迎提问,感谢大家阅读 )