Implementing Single-Activity Architecture with Jetpack Compose Navigation
The article explains how to adopt a single‑Activity architecture in Jetpack Compose by using the Navigation component’s NavHost and NavController, encapsulating navigation calls in an Action class, and exposing module‑specific NavGraphs, resulting in a clean, scalable routing solution for modern Android apps.
With the growing adoption of Jetpack Compose, many projects are moving towards a single‑Activity architecture where a single Activity hosts multiple Compose views and navigation is handled by Compose Navigation.
The “single” in single‑Activity is relative; it can refer to a single Activity per business module or per feature. For new modules or features with multiple screens, using a single Activity + multiple ComposeView together with Compose Navigation is recommended.
The core of implementing a single‑Activity architecture in Compose is the Navigation component. Understanding its usage is essential.
Basic Navigation usage
composeView.setContent {
RainbowTheme() {
Surface(color = Color.Transparent, modifier = Modifier.fillMaxSize()) {
A()
}
}
}Example composables A and B:
@Composable
fun A() {
Button(onClick = {
// navigate to B
}) {
Text("跳转到B")
}
}
@Composable
fun B() {
Text("B页面")
}Define a NavHost:
@Composable
fun NavHostDemo() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "A_route") {
composable("A_route") { A(navController) }
composable("B_route") { B(navController) }
}
}NavController provides two core methods used in this context:
navController.navigate("destination_route") – jump to a target page.
navController.popBackStack() – return to the previous page.
To avoid scattering navigation calls across many composables, encapsulate navigation logic in an Action class:
class MessengerAction(private val navController: NavController, activity: Activity) {
val enterSmsPage: () -> Unit = {
navController.navigate(MessengerRouteConfig.SEND_SMS_MAIN_PAGE)
}
val finishActivity: () -> Unit = {
activity.finish()
}
}Use the Action inside a NavHost:
@Composable
fun MessengerNavHost(startDestination: String, intent: Intent) {
val navController = rememberNavController()
val messengerAction = MessengerAction(navController, this)
NavHost(navController = navController, startDestination = startDestination) {
composable(MESSENGER_MAIN_PAGE) { MessengerView(messengerAction) }
composable(SEND_SMS_MAIN_PAGE) { SmsMainPage(messengerAction) }
}
}Calling messengerAction.enterSmsPage() from any composable triggers the navigation without directly referencing the NavController.
For larger projects with multiple modules, each module can expose its own NavHost as an extension on NavGraphBuilder , and the app module aggregates them.
In summary, adopting a Compose‑based single‑Activity architecture with Navigation and encapsulated Action objects provides a clean, scalable routing solution for modern Android mobile development.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.