Navigation & Intents (Deep Dive)
Master app navigation strategies, dynamic navigation graphs, deep linking, and data sharing with Intents.
Module 8: Navigation & Intents (Deep Dive)
Learning Objectives
By the end of this module, you’ll understand:
- What an Intent really is
- Explicit vs Implicit Intents
- Intent Filters
- Activity launch process
- Tasks
- Back Stack
- Launch Modes
- Deep Links
- PendingIntent
- Jetpack Navigation Component
- Compose Navigation
- Common navigation mistakes
Part 1 — Understanding Intents
1. What Is an Intent?
Most tutorials say:
“An Intent is used to start another Activity.”
That’s true, but incomplete.
A better definition is:
An Intent is a message object that describes an action to be performed.
Notice:
An Intent is not the action.
It is a request.
Think of sending a letter.
You
│
Write Letter
│
Postal Service
│
Recipient
Android works similarly.
Activity A
↓
Intent
↓
Android System
↓
Activity B
The Activity never launches another Activity directly.
It asks Android.
Android decides what happens.
2. Why Doesn’t Activity A Just Create Activity B?
Suppose we could do this:
val activity = SecondActivity()
activity.show()
Problems:
- Android wouldn’t know the Activity exists.
- Lifecycle callbacks wouldn’t run.
- Permissions couldn’t be checked.
- Another app couldn’t launch it.
- Task management would break.
Instead:
Android owns every Activity.
Only Android creates Activities.
3. Intent = Description
Imagine ordering food.
You don’t cook.
You submit:
Pizza
Large
Extra Cheese
The restaurant prepares it.
Similarly:
Intent(
this,
LoginActivity::class.java
)
You’re describing:
“I’d like LoginActivity.”
Android performs the work.
4. Anatomy of an Intent
An Intent can contain:
Intent
├── Action
├── Data
├── Category
├── Extras
└── Flags
Each serves a different purpose.
We’ll examine each.
Action
What should happen?
Examples:
ACTION_VIEW
ACTION_SEND
ACTION_DIAL
ACTION_PICK
ACTION_EDIT
Think of this as the verb.
Data
What should the action operate on?
Example:
https://google.com
or
content://contacts
Extras
Additional information.
Example:
Username
Password
Product ID
Message
These are key-value pairs.
Flags
Special instructions for Android.
Example:
Open in new task
Clear existing task
Reuse Activity
We’ll discuss these later.
5. Explicit Intents
The simplest type.
You know exactly where you want to go.
Example:
Intent(
this,
ProfileActivity::class.java
)
Flow:
HomeActivity
↓
Explicit Intent
↓
ProfileActivity
Android doesn’t need to search.
The destination is specified.
6. Implicit Intents
Now imagine:
You don’t care which app opens a PDF.
You simply want:
Open PDF
Intent:
Intent(Intent.ACTION_VIEW)
Android asks:
“Who can handle this?”
Maybe:
Adobe Reader
Google Drive
Files App
The user chooses.
Another example:
Intent(Intent.ACTION_DIAL)
Android opens whichever dialer app is installed.
7. Intent Resolution
Suppose you write:
ACTION_VIEW
↓
https://youtube.com
Android searches installed apps.
Chrome
Firefox
Edge
Opera
If one default exists:
Open it.
If several qualify:
Show a chooser (unless a default has been selected).
Part 2 — Intent Filters
8. How Does Android Know Who Can Handle an Intent?
The answer:
Intent Filters.
Inside AndroidManifest:
<intent-filter>
</intent-filter>
Think of it as advertising.
Example:
My App Supports
↓
https://myshop.com
Android records that information.
9. Example
Suppose Chrome receives:
https://amazon.com
Android asks:
Who handles websites?
Apps answer through intent filters.
10. Launcher Intent
Why does your app appear in the launcher?
Because of this:
ACTION_MAIN
+
CATEGORY_LAUNCHER
Without it,
Android installs the app,
but it won’t appear in the app drawer.
Part 3 — Passing Data
Suppose:
Product List
↓
Product Details
Need Product ID.
Extras solve this.
intent.putExtra(
"productId",
25
)
Receive:
intent.getIntExtra(
"productId",
-1
)
Flow:
Activity A
↓
Intent
↓
Extras
↓
Activity B
For larger or more structured data, Android supports Parcelable (preferred for Android) and Serializable (simpler but slower).
Part 4 — Tasks
This is where many developers get confused.
11. What Is a Task?
A Task is not an Activity.
A Task is:
A collection of Activities the user works through to accomplish a goal.
Example:
Login
↓
Dashboard
↓
Profile
↓
Settings
These Activities belong to one Task.
Think of a Task as a stack of screens representing one user journey.
12. The Back Stack
Android stores Activities like a stack.
Example:
Home
↓
Products
↓
Details
↓
Checkout
Internally:
Top
Checkout
Details
Products
Home
Press Back:
Checkout removed.
Next:
Details.
Another Back:
Products.
This is the default Android navigation model.
13. Activity Stack Example
Imagine:
A
↓
B
↓
C
↓
D
Memory:
Top
D
C
B
A
Back:
Top
C
B
A
The last Activity is destroyed (or at least finished and removed from the task).
Part 5 — Launch Modes
Suppose the user repeatedly opens:
Home
↓
Settings
↓
Settings
↓
Settings
↓
Settings
Now there are multiple instances of the same Activity.
Sometimes that’s undesirable.
Launch modes help control this behavior.
Standard
Default.
Every launch creates a new Activity.
A
↓
B
↓
B
↓
B
SingleTop
If the requested Activity is already at the top of the stack,
reuse it.
A
↓
B
Launch B again:
Still:
A
↓
B
Instead of creating another instance.
SingleTask
Reuse an existing instance within a task and clear Activities above it.
Example:
A
↓
B
↓
C
↓
D
Launch B.
Result:
A
↓
B
C and D are removed.
SingleInstance
Rarely used.
The Activity runs in its own dedicated task.
You’ll encounter it infrequently in everyday app development.
Part 6 — Deep Links
Suppose someone taps:
https://shop.com/products/15
Instead of opening the browser,
your app opens directly to:
Product Screen
↓
Product #15
That’s a Deep Link.
Flow:
Website
↓
Intent
↓
Android
↓
Your App
Android matches the URL against your app’s intent filters.
Part 7 — PendingIntent
This concept confuses many developers.
Imagine you want Android to perform an action later, even when your app isn’t running.
Example:
Notification:
New Message
↓
User taps later
↓
Chat Screen Opens
When the notification is created, your app may no longer be in the foreground when it’s tapped.
A PendingIntent is like giving Android a sealed, pre-authorized Intent that it can execute on your app’s behalf at a later time.
Common uses:
- Notifications
- AlarmManager
- App Widgets
Part 8 — Navigation Component
Managing Fragment transactions manually becomes tedious.
Old approach:
beginTransaction()
replace()
commit()
Modern approach:
Navigation Graph
↓
NavController
↓
Navigate
Google introduced the Navigation Component to simplify navigation.
Navigation Graph
Instead of hardcoding navigation,
you define destinations.
Home
↓
Details
↓
Cart
↓
Checkout
The Navigation Component understands this graph.
NavController
Responsible for navigation.
Example:
findNavController().navigate(
R.id.detailsFragment
)
The NavController updates the Fragment stack and handles transitions.
Safe Args (XML Navigation)
Instead of:
String Keys
↓
"productId"
Safe Args generates type-safe classes.
Benefits:
- Compile-time checking
- Auto-completion
- Reduced runtime errors
Part 9 — Compose Navigation
Compose doesn’t navigate using Fragments.
Instead:
NavHost
↓
Composable
↓
Composable
↓
Composable
Example:
NavHost(...)
Destinations are composable functions rather than Fragments.
Conceptually, though, the ideas of a back stack and navigation graph remain.
Activity Navigation vs Compose Navigation
| Activities | Compose |
|---|---|
| Intent | NavController |
| Activity | Composable destination |
| FragmentManager | Compose Navigation |
| Back Stack | Navigation Back Stack |
| XML Navigation | Kotlin DSL |
Common Navigation Mistakes
Mistake 1
Passing large objects through Intents.
Instead:
Pass an ID.
Reload the object from the repository or database.
Mistake 2
Using global mutable variables to share data.
Prefer:
- ViewModel
- Repository
- SavedStateHandle
- Persistent storage (when appropriate)
Mistake 3
Ignoring the Back Stack.
Always think about:
What should happen when the user presses Back?
Design your navigation flow with this in mind.
Mistake 4
Using the wrong launch mode.
Most Activities should simply use the default (standard) unless you have a specific reason to change it.
Real-World Example
Imagine an e-commerce app.
Launcher
↓
Home
↓
Product
↓
Cart
↓
Checkout
↓
Payment
↓
Confirmation
The task now contains:
Top
Confirmation
Payment
Checkout
Cart
Product
Home
Press Back repeatedly:
Confirmation
↓
Payment
↓
Checkout
↓
Cart
↓
Product
↓
Home
↓
Exit App
Now imagine the user taps a notification:
Order Shipped
Android executes a PendingIntent that deep-links directly to the Order Details screen.
The system may create or reuse the task depending on how the PendingIntent and Activity are configured.
Best Practices
- Use explicit Intents for navigation within your app.
- Use implicit Intents when asking the system to perform an action (share, dial, view, etc.).
- Pass lightweight identifiers rather than large objects.
- Understand how the back stack should behave before implementing navigation.
- Use the Navigation Component (or Compose Navigation) instead of manual Fragment transactions for most new apps.
- Use launch modes sparingly and only when they solve a real problem.
Mental Model
Think of Android navigation as a postal system:
Your Code
│
Create Intent
│
Android System
│
Resolve Destination
│
Launch Activity / App
For navigation inside your app, the destination is explicit.
For system-wide actions, Android resolves the best app using intent filters.
Interview Questions
- What is an Intent, and why does Android use it?
- Explain the difference between explicit and implicit Intents.
- What information can an Intent contain?
- How does Android resolve an implicit Intent?
- What is an Intent Filter?
- What is the difference between a Task and the Back Stack?
- Explain the different Activity launch modes and when you might use them.
- What is a Deep Link?
- What is a PendingIntent, and why can’t a normal Intent be used in notifications?
- Compare traditional Activity/Fragment navigation with Jetpack Compose Navigation.
Next Module: RecyclerView (and LazyColumn in Compose)
This module is where we’ll study one of Android’s most performance-critical UI components.
We’ll go much deeper than “RecyclerView displays lists.” We’ll explore:
- Why
ListViewwasn’t enough. - The recycling mechanism.
- How
RecyclerViewavoids creating thousands of Views. Adapter,ViewHolder, andLayoutManagerinternals.DiffUtiland efficient list updates.- Performance optimizations.
- How
LazyColumnachieves similar goals in Jetpack Compose.
By the end, you’ll understand why RecyclerView is considered one of Android’s most important UI components and how to use it efficiently in production apps.