Dalam aplikasi Android yang lebih dari satu layar, kita pasti perlu memanggil Activity lain atau membuka sumber daya eksternal. Mekanisme utamanya adalah Intent. Selain Intent tradisional, Jetpack juga menyediakan Navigation Component untuk mengelola alur antar Fragment dengan lebih terstruktur. Bab ini menjelaskan perbedaan kedua pendekatan, kapan memakai masing-masing, dan jebakan umum yang sering ditemui pemula.
Explicit Intent #
Explicit Intent menyebutkan nama kelas Activity target secara langsung. Sistem operasi akan meluncurkan Activity tersebut tanpa perlu mencocokkan filter. Bentuk dasarnya:
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("EXTRA_ID", 42)
}
startActivity(intent)Parameter putExtra mengirim data tambahan ke Activity target. Activity target membacanya kembali lewat intent.getIntExtra("EXTRA_ID", -1) di onCreate. Konvensi penamaan key dengan prefix EXTRA_ dan nama kelas pemilik (mis. DetailActivity.EXTRA_ID) membantu menghindari tabrakan key antar modul.
Implicit Intent #
Implicit Intent tidak menyebutkan target, melainkan aksi dan data yang harus dipenuhi. Sistem operasi memilih aplikasi yang dapat menangani aksi tersebut melalui mekanisme intent resolution. Contoh klasik: membuka URL di browser.
val urlIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))
startActivity(urlIntent)Jika tidak ada aplikasi yang cocok, startActivity akan melempar ActivityNotFoundException. Mulai Android 11 (API 30), aplikasi hanya dapat melihat package lain yang secara eksplisit dideklarasikan di AndroidManifest.xml lewat tag <queries>. Tanpa deklarasi tersebut, implicit intent ke aplikasi pihak ketiga akan diam-diam gagal.
Simulasi Router dan Back Stack #
Cuplikan berikut memodelkan explicit dan implicit intent sebagai data class serta router yang menyimpan back stack. Kita dapat memanggil startActivity dan popBackStack untuk melihat urutan transisi:
// intents_navigation.kt
// Mensimulasikan explicit intent (startActivity), implicit intent (action + data),
// dan back stack Navigation Component sebagai model data ringkas yang dapat
// dijalankan tanpa Android SDK.
data class Intent(val action: String?, val data: String?, val target: String?) {
companion object {
fun explicit(target: String): Intent = Intent(action = null, data = null, target = target)
fun implicit(action: String, data: String): Intent = Intent(action = action, data = data, target = null)
}
}
class ActivityRouter {
private val backStack = ArrayDeque<String>()
private val registeredActivities = mapOf(
"MainActivity" to listOf(Intent.explicit("DetailActivity")),
"DetailActivity" to listOf(Intent.implicit("android.intent.action.VIEW", "https://example.com"))
)
fun startActivity(intent: Intent) {
val target = when {
intent.target != null -> intent.target
intent.action == "android.intent.action.VIEW" -> "BrowserActivity"
else -> null
}
requireNotNull(target) { "Tidak ada handler untuk intent $intent" }
backStack.addLast(target)
println("startActivity -> $target (data=${intent.data ?: '-'})")
}
fun popBackStack(): String? {
val popped = backStack.removeLastOrNull()
println("popBackStack -> ${popped ?: "kosong"}")
return popped
}
fun currentDestination(): String? = backStack.lastOrNull()
fun stackSize(): Int = backStack.size
}
object NavRoutes {
const val HOME = "home"
const val DETAIL = "detail/{id}"
const val SETTINGS = "settings"
fun detailRoute(id: Int): String = "detail/$id"
}
fun main() {
val router = ActivityRouter()
router.startActivity(Intent.explicit("MainActivity"))
router.startActivity(Intent.explicit("DetailActivity"))
router.startActivity(Intent.implicit("android.intent.action.VIEW", "https://example.com"))
println("Stack size: ${router.stackSize()}, current: ${router.currentDestination()}")
println("Navigasi Compose route: ${NavRoutes.detailRoute(42)}")
router.popBackStack()
router.popBackStack()
router.popBackStack()
println("Stack size akhir: ${router.stackSize()}")
}Output yang Dihasilkan:
startActivity -> MainActivity (data=-)
startActivity -> DetailActivity (data=-)
startActivity -> BrowserActivity (data=https://example.com)
Stack size: 3, current: BrowserActivity
Navigasi Compose route: detail/42
popBackStack -> BrowserActivity
popBackStack -> DetailActivity
popBackStack -> MainActivity
Stack size akhir: 0Perhatikan bahwa implicit intent ke https://example.com diarahkan ke BrowserActivity oleh router. Pada peranti nyata, sistem operasi memilih berdasarkan intent filter yang dideklarasikan oleh aplikasi yang terpasang.
Navigation Component untuk Fragment #
Untuk aplikasi satu Activity banyak Fragment (atau satu Compose dengan banyak screen), Navigation Component menyediakan cara terstruktur. Alur didefinisikan sebagai grafik di res/navigation/nav_graph.xml atau dengan DSL Compose. Setiap node memiliki route, dan argumen dideklarasikan secara type-safe:
NavHost(navController = navController, startDestination = "home") {
composable("home") { HomeScreen(onItemClick = { id ->
navController.navigate("detail/$id")
}) }
composable("detail/{id}") { backStackEntry ->
val id = backStackEntry.arguments?.getString("id")?.toIntOrNull() ?: -1
DetailScreen(id)
}
}Navigasi antar route memakai navController.navigate("detail/42"). Tombol Back otomatis memanggil popBackStack() sepanjang back stack. Type-safe args dapat dicapai dengan plugin Navigation Compose terbaru yang memakai Kotlin Serialization untuk men-generate route builder.
Kapan Pakai Intent vs Navigation Component #
| Skenario | Pendekatan |
|---|---|
| Membuka Activity lain dalam aplikasi | Intent eksplisit (klasik) atau Compose Navigation |
| Membuka URL, bagikan teks, ambil foto | Intent implisit + chooser |
| Aplikasi Jetpack Compose multi-screen | Compose Navigation + NavHost |
| Memulai Service atau mengirim broadcast | Intent dengan startService / sendBroadcast |
Referensi Lanjutan #
- Navigation — panduan resmi komponen Navigation Android Jetpack untuk perpindahan antar destinasi
Selanjutnya #
Setelah Activity dapat diluncurkan, langkah berikutnya adalah menampilkan sesuatu di dalamnya. Kita akan membahas LinearLayout, ConstraintLayout, TextView, Button, dan RecyclerView pada chapter Layouts dan UI Components.