Why This Topic Matters Now
If you're building your first Android app, you've probably heard the term "Activity" thrown around. But what is it, really? And why does it matter so much that you get it right? Think of an Activity as a single screen in your app—like a room in a house. Just as a house has a kitchen, a living room, and a bedroom, your app has different screens: a login screen, a main menu, a settings page. Each of those screens is an Activity.
But here's the thing: unlike a real room, an Android Activity has a life of its own. It gets created, started, paused, stopped, and destroyed—often without you doing anything. If you don't understand this lifecycle, your app will crash, lose data, or confuse users. That's why this topic is the bedrock of Android development.
When you're a beginner, it's tempting to jump straight to fancy UI or networking code. But the Activities are the skeleton of your app. If the skeleton is weak, nothing else holds up. Many tutorials gloss over the lifecycle, assuming you'll pick it up later. But later is when your app is already in the Play Store and users are complaining that their progress disappeared after they rotated their phone.
This guide is for you if you've written a few lines of Kotlin or Java, maybe followed a "Hello World" tutorial, but still feel shaky on how screens connect. We'll use the room-and-door analogy throughout, because it sticks. By the end, you'll know how to design your app's flow, pass data between screens, and handle the back button like a pro.
Who Should Read This
If you're a self-taught developer, a bootcamp grad, or a student taking your first mobile course, this is your starting point. We assume you know basic programming concepts (variables, functions, classes) but nothing about Android yet. You don't need to have Android Studio installed—though you'll want it open by the time we get to the walkthrough.
What You'll Be Able to Do After Reading
After this guide, you'll be able to explain what an Activity is to a friend, create a new Activity in Android Studio, start it with an Intent, pass data using extras, handle the back button, and avoid common lifecycle pitfalls. You'll also have a mental model for thinking about app navigation that will serve you for years.
The Core Idea: Activities as Rooms, Intents as Doors
Imagine your app is a house. Each room serves a purpose: the kitchen is for cooking, the bedroom is for sleeping. In your app, each screen has a purpose: a login screen is for authentication, a gallery screen is for viewing photos. These screens are Activities.
Now, how do you move from one room to another? You walk through a door. In Android, that door is called an Intent. An Intent is a message that says, "I want to go to this room." It can also carry a suitcase with data—like a username or a product ID.
But there's a twist: the house has a back door. When you press the back button, Android takes you to the previous room you were in. This is managed by the "back stack," which is like a history of rooms you've visited. Each time you open a new Activity, Android pushes it onto the stack. When you press back, it pops the top Activity off and you return to the previous one.
This analogy is powerful because it maps directly to code. When you write startActivity(Intent), you're opening a door. When you write finish(), you're closing the current room and stepping back. Understanding this makes everything else click.
What an Activity Is Not
An Activity is not a fragment, a view, or a service. Fragments are like furniture inside a room—they live inside an Activity. Views are the individual objects (buttons, text fields) that make up the room's decor. Services run in the background, like a furnace—they don't have a visible room. Keep these separate in your mind.
Why the Analogy Works
New developers often struggle because they think of Activities as "pages" in a book. But a book has a fixed order; you turn pages forward and backward. An app is more like a house where you can wander freely, open doors from anywhere, and even have multiple doors leading to the same room. The room-and-door analogy captures that flexibility.
How It Works Under the Hood
Every Activity in Android goes through a well-defined lifecycle. The system calls specific methods as the Activity moves between states: onCreate(), onStart(), onResume(), onPause(), onStop(), and onDestroy(). You override these methods to do your setup and cleanup.
Think of it like a restaurant kitchen. When a new chef (Activity) arrives, they first onCreate()—unpack their knives, preheat the oven. Then onStart()—the kitchen becomes visible but not yet ready to serve. Then onResume()—the chef is actively cooking. If the phone rings (an incoming call), the chef onPause()—they stop cooking but keep everything ready. If the call lasts too long, the kitchen onStop()—the chef steps out. Eventually, the shift ends and onDestroy()—the chef leaves, kitchen cleaned.
This lifecycle is not optional. If you don't save your data in onPause() or onSaveInstanceState(), you'll lose it when the user rotates the screen (which destroys and recreates the Activity). That's the number one beginner mistake.
The Back Stack in Detail
The back stack is a last-in-first-out (LIFO) structure. When you start Activity B from Activity A, B is pushed onto the stack. Pressing back pops B, and A resumes. But what if you don't want A to remain? You can call finish() on A before starting B, so A is removed. This is common in login flows: after logging in, you don't want the user to go back to the login screen.
Launch Modes
Android provides launch modes that change how Activities are added to the stack. The default is standard, which creates a new instance every time. singleTop reuses an existing instance if it's at the top of the stack. singleTask and singleInstance are for more complex scenarios, like a music player that should only have one instance. Most beginners can stick with the default until they hit a problem.
Worked Example: A Login Flow
Let's build a simple two-Activity app: a LoginActivity and a MainActivity. The user enters their username and password, taps Login, and if successful, they see the MainActivity. Pressing back from MainActivity should exit the app, not return to login.
First, create a new Android project with an Empty Activity. Name it LoginActivity. In the layout, add an EditText for username, an EditText for password, and a Button. In the Kotlin code, handle the button click:
val loginButton = findViewById<Button>(R.id.login_button)
loginButton.setOnClickListener {
val username = findViewById<EditText>(R.id.username).text.toString()
val password = findViewById<EditText>(R.id.password).text.toString()
if (username == "user" && password == "pass") {
val intent = Intent(this, MainActivity::class.java)
intent.putExtra("USERNAME", username)
startActivity(intent)
finish() // remove LoginActivity from stack
}
}Notice the finish() call. Without it, pressing back on MainActivity would return to LoginActivity—bad UX. With finish(), the back button exits the app.
Now create MainActivity with a simple layout that displays the username. In its onCreate(), retrieve the extra:
val username = intent.getStringExtra("USERNAME")
val greeting = findViewById<TextView>(R.id.greeting)
greeting.text = "Welcome, $username!"That's it. You've just built a complete navigation flow.
Passing Complex Data
For more than a few strings, use a data class and serialize it. You can make the class implement Parcelable or use a library like Gson to convert to JSON. Pass the JSON string as an extra, then parse it in the target Activity.
Handling the Back Button
By default, the back button pops the stack. If you want to intercept it (e.g., to confirm exit), override onBackPressed() in your Activity. For example, show a dialog asking "Are you sure?" before finishing.
Edge Cases and Exceptions
Real apps aren't as simple as the login example. Here are common edge cases you'll face.
Configuration Changes (Screen Rotation)
When the user rotates their phone, Android destroys and recreates the current Activity by default. If you have a running task (like a network request), it will be interrupted. The solution is to save the instance state in a Bundle in onSaveInstanceState() and restore it in onCreate(). For more complex state, use a ViewModel (from Android Architecture Components) which survives configuration changes.
Process Death
If the system kills your app to free memory (e.g., because the user hasn't interacted with it for a while), the entire task is destroyed. When the user returns, Android recreates the last Activity and restores the saved instance state. But if you were in the middle of a multi-step flow, you need to save that progress. Use onSaveInstanceState() for lightweight data, and a persistent storage (like Room or SharedPreferences) for important user data.
Deep Links
Deep links allow other apps to open a specific Activity in your app. For example, a news app might open an article directly. To support deep links, add an intent filter in your manifest for the target Activity. The incoming Intent will contain data (like a URL) that you parse to determine what to show.
Testing deep links is tricky. Use the Android Debug Bridge (ADB) to simulate a deep link: adb shell am start -W -a android.intent.action.VIEW -d "example://article/123" com.example.myapp.
Limits of the Approach
While Activities are fundamental, they aren't the only way to build screens. Modern Android development often uses Jetpack Compose, which replaces Activities and Fragments with composable functions. However, Activities still exist as entry points. Even in Compose, you'll have at least one Activity that hosts your composables.
Another limit is complexity. If your app has many screens, managing the back stack with Activities alone becomes messy. That's why navigation libraries like the Jetpack Navigation Component were created. They handle fragment transactions and back stack management for you, reducing boilerplate and bugs.
Activities also have overhead. Each Activity is a heavyweight object with its own lifecycle. For simple dialogs or full-screen ads, consider using a DialogFragment or an Activity with a dialog theme instead of a full Activity.
When Not to Use Activities
If you're building a single-screen app (like a calculator), you only need one Activity. If you're building a complex app with multiple screens, consider using Fragments or Compose inside a single Activity. This gives you more control over the UI and reduces the number of Activity lifecycle callbacks to manage.
Alternatives to Intents
For navigation within your app, consider using the Navigation Component. It provides a visual editor for routes, type-safe arguments, and automatic back stack handling. It's the recommended approach for most apps.
Reader FAQ
What's the difference between an Activity and a Fragment?
An Activity is a screen that can contain multiple Fragments. Fragments are reusable UI components that live inside an Activity. Think of an Activity as a room and Fragments as furniture groupings within that room. You can swap Fragments without changing the Activity.
Can I have an app with no Activities?
No, every Android app needs at least one Activity to launch. Even if you use Compose, you need an Activity to host the composable tree. Services and BroadcastReceivers can run without an Activity, but they can't display UI.
How do I pass data back from Activity B to Activity A?
Use startActivityForResult() (deprecated in newer APIs) or the Activity Result API. In Activity A, register a result callback. In Activity B, set the result with an Intent and call finish(). The callback in A receives the data.
What happens if I don't call finish() after starting a new Activity?
The previous Activity stays in the back stack. Pressing back will return to it. This is fine for many flows (e.g., a list to detail screen), but not for login screens or splash screens where you don't want users to go back.
Why does my Activity restart when I rotate the phone?
By default, Android destroys and recreates the Activity on configuration changes to load the correct resources (like landscape layout). To prevent this, you can handle the configuration change yourself by adding android:configChanges="orientation|screenSize" to the manifest, but that's rarely recommended. Instead, save state in onSaveInstanceState() and restore it.
Practical Takeaways
You now have a solid mental model for Android Activities. Here are your next steps:
- Open Android Studio and create a new project with two Activities. Implement the login flow we walked through.
- Add a third Activity and practice passing data between all three. Experiment with
finish()and see how the back stack changes. - Rotate your device while in an Activity and observe the lifecycle calls. Add log statements to each lifecycle method to see the order.
- Read the official Android documentation on the Activity lifecycle and launch modes. It will reinforce what you learned here.
- Try the Jetpack Navigation Component in a small project. You'll appreciate how it simplifies back stack management.
Remember, every Android developer started where you are. The key is to build something, break it, and fix it. Your app's rooms and doors are waiting—go design them.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!