Activities and Navigation in Android

    Atul Kabra4 min readUpdated

    Activities and Navigation in Android

    An activity is a single entry point into your app, roughly a window the system can launch. Modern apps often use one activity that hosts many Compose screens, and they switch between those screens with Navigation Compose rather than launching a new activity per screen. This article explains the activity lifecycle you must respect, then shows how to navigate between Compose destinations and pass data along.

    What an Activity Is

    When the user taps your app icon, Android starts your launcher activity. Historically each screen was its own activity. Today the common pattern is a single MainActivity that calls setContent { ... } and then uses navigation inside Compose to show different screens. Fewer activities means simpler state handling.

    The Activity Lifecycle

    The system calls lifecycle methods as your activity is created, shown, hidden, and destroyed. You do not control exactly when these happen (a phone call, rotation, or low memory can trigger them), so you must handle them gracefully.

    The key callbacks, in order of a typical session:

    • onCreate – set up the UI; called once when the activity is created.
    • onStart – the activity becomes visible.
    • onResume – the activity is in the foreground and interactive.
    • onPause – another screen is partially covering it; save light state here.
    • onStop – no longer visible.
    • onDestroy – being removed from memory.
    import android.os.Bundle
    import android.util.Log
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    
    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.d("Lifecycle", "onCreate") // runs once when created
            setContent {
                AppNavigation() // host the navigation graph
            }
        }
    
        override fun onPause() {
            super.onPause()
            Log.d("Lifecycle", "onPause") // good place to save quick state
        }
    }
    

    Navigating Between Screens with Navigation Compose

    Navigation Compose gives you a NavController and a NavHost that maps string routes to composable screens. You call navController.navigate("route") to move forward and navController.popBackStack() to go back.

    import androidx.compose.material3.Button
    import androidx.compose.material3.Text
    import androidx.compose.runtime.Composable
    import androidx.navigation.compose.NavHost
    import androidx.navigation.compose.composable
    import androidx.navigation.compose.rememberNavController
    
    @Composable
    fun AppNavigation() {
        // the controller remembers the back stack of screens
        val navController = rememberNavController()
    
        // the NavHost declares which composable shows for each route
        NavHost(navController = navController, startDestination = "home") {
            composable("home") {
                // pass a lambda so the screen can request navigation
                HomeScreen(onOpenDetails = { navController.navigate("details") })
            }
            composable("details") {
                DetailsScreen(onBack = { navController.popBackStack() })
            }
        }
    }
    
    @Composable
    fun HomeScreen(onOpenDetails: () -> Unit) {
        Button(onClick = onOpenDetails) { Text("Open details") }
    }
    
    @Composable
    fun DetailsScreen(onBack: () -> Unit) {
        Button(onClick = onBack) { Text("Go back") }
    }
    

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses

    Passing Data Between Screens

    You can include arguments in the route. Keep them small, identifiers rather than whole objects.

    // Define a route with a placeholder argument
    composable("profile/{userId}") { backStackEntry ->
        // read the argument from the back stack entry
        val userId = backStackEntry.arguments?.getString("userId")
        ProfileScreen(userId = userId)
    }
    
    // Navigate with a real value:
    // navController.navigate("profile/42")
    

    Pass an ID and let the destination screen load the rest of the data. Do not try to pass large objects through navigation arguments.

    Common Mistakes

    • Putting setup logic in onResume that should be in onCreate. onResume can run many times; one-time setup belongs in onCreate.
    • Doing slow work in lifecycle callbacks. Network or disk work on the main thread freezes the UI. Move it off the main thread with coroutines.
    • Creating a new activity for every screen. For most apps a single activity with Navigation Compose is simpler and avoids state-passing headaches.
    • Passing big objects as navigation arguments. Pass an ID and reload the data. Large arguments are fragile and can crash.
    • Forgetting that rotation recreates the activity. Unsaved state is lost unless you store it properly (for example with a ViewModel).

    FAQ

    Do I need to memorise every lifecycle method? No, but know that the activity can be paused, stopped, and recreated at any time, and design so nothing important is lost.

    Is one activity really enough? For many apps, yes. Navigation Compose handles multiple screens within a single activity cleanly.

    How do I go back? Call navController.popBackStack(), or let the system back button do it; Navigation Compose manages the back stack.

    Keep Going

    To make screens that survive rotation and hold data, you will soon want persistence; see Local Storage in Android. To design the screens themselves, revisit Layouts and UI in Android. The full path is at the Android learning hub.


    Want guided practice building multi-screen apps? Join the waitlist for the Android Development course at Infoplanet in Jalgaon.

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses
    Atul Kabra

    Founder, Infoplanet

    Atul Kabra founded Infoplanet in 2001 and has spent over two decades teaching programming — C, C++, Java, databases and more — to students across Maharashtra.

    Related guides