20240217
创建拥有多的页面的单Activity应用,使用Jetpack的导航和其他组件
1. 介绍
在这个记账本App中,我们不仅需要一个页面来记录支出和收入,还需要一个页面来显示支出和收入的统计信息。当然我们可以使用两个Activity来实现这个功能,但是Google更推荐的方式是使用单Activity多Fragment的架构。这样做可以更方便的管理页面之间的导航和数据传递,以及让界面之间的过渡更加自然。
首先考虑一下要做什么,一个方便在页面中切换的底部导航菜单,一个页面用来记录支出和收入,一个页面用来显示支出和收入的统计信息。这里我们可以使用Jetpack的导航组件来管理页面之间的导航,使用JetpackCompose来实现页面的UI。
2. 单Activity的应用文件架构
在单Activity的应用中,我们的Activity只负责管理Fragment的切换,所有的页面逻辑都在Fragment中实现。这样做的好处是可以更方便的管理页面之间的导航和数据传递,以及让界面之间的过渡更加自然。
这里我们的创建项目的架构,就可以将每个页面的Screen.kt和ViewModel.kt放在一起,这样可以更方便的管理每个页面的逻辑。
例如:
├── MainActivity.kt
├── data
│ ├── Expense.kt
│ └── ExpenseRepository.kt
├── ui
│ ├── expense_statistics
│ │ ├── ExpenseStatisticsScreen.kt
│ │ └── ExpenseStatisticsViewModel.kt
│ └── home
│ ├── HomeScreen.kt
│ └── HomeViewModel.kt
└── MainActivity.kt
...
3. 使用Jetpack的导航组件
在单Activity的应用中,我们可以使用Jetpack的导航组件来管理页面之间的导航。这样可以更方便的管理页面之间的导航和数据传递,以及让界面之间的过渡更加自然。
在这里我们可以使用NavHostFragment
来托管我们的Fragment,使用NavGraph
来管理页面之间的导航。这里我们的view使用JetpackCompose来实现,所以我们可以使用NavHost
来托管我们的Compose页面。
然后我们可以使用BottomNavigation
来实现底部导航菜单,使用NavHostController
来管理页面之间的导航。
例如:
@Composable
fun MainScreen() {
val navController = rememberNavController()
Scaffold(
bottomBar = {
BottomNavigation {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
items.forEach { screen ->
BottomNavigationItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = { Text(screen.label) },
selected = currentRoute == screen.route,
onClick = {
navController.navigate(screen.route) {
popUpTo = navController.graph.startDestination
launchSingleTop = true
}
}
)
}
}
}
) {
NavHost(navController, startDestination = Screen.Home.route) {
composable(Screen.Home.route) { HomeScreen() }
composable(Screen.ExpenseStatistics.route) { ExpenseStatisticsScreen() }
}
}
}
4. 使用JetpackCompose实现页面的UI
在这里我们可以使用JetpackCompose来实现页面的UI,界面的内容省略。
例如:
@Composable
fun HomeScreen() {
// 界面的内容省略
}
@Composable
fun ExpenseStatisticsScreen() {
// 界面的内容省略
}
5. 使用Jetpack的ViewModel来管理页面的逻辑
在这里我们可以使用Jetpack的ViewModel来管理页面的逻辑,这样可以更方便的管理页面的逻辑。
例如:
class HomeViewModel : ViewModel() {
// 页面的逻辑省略
}
class ExpenseStatisticsViewModel : ViewModel() {
// 页面的逻辑省略
}