安卓软件开发:Jetpack Compose Material3结合 MVVM 架构的模块化架构设计和实践

2024-10-09 15:17:21 浏览数 (5)

2024年已经过半,作为一名聋人独立开发者,我常常反思这半年的进步与收获。在这篇文章中,我将分享如何使用 Jetpack ComposeMaterial3 结合 MVVM 架构设计一个模块化的Android应用。无论你是新手开发者,还是有经验的安卓开发人员,相信这篇文章都会对你有所帮助。

一、为什么需要模块化架构?

模块化设计的好处是:

可扩展性:各模块独立开发,彼此依赖最小化,方便新功能的添加和扩展。

  1. 代码复用:通用组件可以封装成独立模块,方便在项目中复用。
  2. 提高开发效率:不同团队可以并行开发各自负责的模块,减少相互依赖。
  3. 易维护:当某个模块出现问题时,定位和修复很方便。

二、模块化架构

几个模块划分:

  1. UI 层:负责界面的渲染和用户交互的逻辑。
  2. 数据层:处理数据的获取、存储及管理,和数据库和 API 交互。
  3. 业务逻辑层 (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 持久化数据。

代码语言:java复制
@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 层的状态。

代码语言:java复制
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 负责管理界面上的数据,用 LiveDataFlow 来更新数据,这样界面就能自动刷新了。

4.3 UI 层

ui/theme: theme 模块负责App的整体 UI 风格定义,如颜色、排版等。

代码语言:java复制
@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。

代码语言:java复制
@Composable
fun HomeScreen(viewModel: WishViewModel) {
    val wishes by viewModel.wishes.observeAsState(initial = emptyList())

    LazyColumn {
        items(wishes) { wish ->
            Text(text = wish.title)
        }
    }
}

五、页面间导航的实现

提供了内置的导航组件管理页面间的跳转。导航逻辑放置在 MainScreen 中。

代码语言:java复制
@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 更新的核心,通过 StateLiveData,可以让 UI 层随着数据变化而自动重绘。

代码语言:java复制
@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 层

负责页面的渲染和用户交互,用 ComposeMaterial3 提供的组件构建美观 UI。

在开发时,把东西分开来做,能让应用更容易维护和升级,这种模块化的方法很不错。

有任何问题欢迎提问,感谢大家阅读 )

0 人点赞