Anotasi @Composable — elemen fundamental Jetpack Compose yang mengubah fungsi Kotlin biasa menjadi blok bangunan deklaratif antarmuka pengguna. Tanpa anotasi ini, tidak ada satu pun layar yang dapat dibuat dalam pengembangan Android modern. Menurut Google Android Developers, 2026, lebih dari 80% proyek baru di Kotlin menggunakan Compose untuk membangun UI, dan @Composable adalah anotasi yang paling sering digunakan di ekosistem.
Utama
@Composable — adalah anotasi bahasa Kotlin yang menandai fungsi sebagai ditujukan untuk mendeskripsikan antarmuka pengguna dalam kerangka Jetpack Compose. Ketika kompiler Kotlin menemukan anotasi ini, ia menghasilkan kode tambahan yang memungkinkan fungsi bekerja dalam konteks komposisi — sistem manajemen pohon UI.
Anotasi @Composable diperkenalkan oleh Google pada tahun 2021 bersamaan dengan versi stabil pertama Jetpack Compose 1.0. Sebelum kemunculannya, pengembangan antarmuka untuk Android dilakukan secara eksklusif melalui markup XML dan sistem View. @Composable mengubah pendekatan secara radikal: alih-alih mendeskripsikan UI dalam file markup terpisah, programmer menulis antarmuka langsung di Kotlin.
Perbedaan utama antara @Composable dan fungsi Kotlin biasa — kemampuan untuk membaca dan bereaksi terhadap perubahan status. Ketika variabel yang dibaca fungsi Composable berubah nilainya, sistem secara otomatis menjadwalkan mulai ulang (rekomposisi) fungsi tersebut. Ini membebaskan programmer dari pembaruan UI manual melalui findViewById dan setText.
Mekanika internal @Composable didasarkan pada konsep slot — area memori khusus yang dialokasikan untuk setiap fungsi dalam komposisi. Di slot ini disimpan nilai yang diteruskan ke fungsi, serta informasi layanan yang diperlukan untuk perbandingan pada panggilan berikutnya.
Untuk mendeklarasikan fungsi Composable, cukup tambahkan anotasi @Composable sebelum kata kunci fun. Fungsi harus berada dalam paket yang mengimpor anotasi dari androidx.compose.runtime. Nama fungsi disarankan ditulis dengan huruf kapital — ini adalah konvensi umum yang diterima di komunitas Compose yang membedakan komponen UI dari fungsi biasa secara visual.
import androidx.compose.runtime.Composable
@Composable
fun Greeting(name: String) {
var count by remember { mutableStateOf(0) }
Column {
Text("Halo, $name!")
Button(onClick = { count++ }) {
Text("Diklik $count kali")
}
}
}
Parameter fungsi Composable bisa apa saja — tipe primitif, string, lambda, dan bahkan fungsi Composable lain yang diteruskan melalui Slot API. Disarankan untuk membuat parameter tidak dapat diubah (val) untuk menghindari efek samping saat rekomposisi. Semua data yang dapat diubah harus dikelola melalui mekanisme status Compose.
Fungsi Composable tidak dapat mengembalikan nilai sembarang seperti fungsi biasa — satu-satunya tugas mereka adalah membangun atau memperbarui fragmen pohon UI. Namun ada pola khusus seperti State Hoisting, di mana fungsi Compose menerima status dan callback melalui parameter, tetap murni dan dapat digunakan kembali.
Sistem Compose memberlakukan beberapa batasan ketat tentang bagaimana fungsi Composable harus terlihat dan berperilaku. Aturan pertama: fungsi Composable hanya dapat memanggil fungsi Composable lain atau fungsi biasa tanpa efek samping. Ini memastikan prediktabilitas komposisi dan kerja optimalisasi Compose yang benar.
Aturan kedua menyangkut urutan eksekusi. Compose berhak memanggil fungsi Composable dalam urutan apa pun, jadi kode dalam tubuh fungsi semacam itu tidak boleh bergantung pada urutan pemanggilan fungsi tetangga. Setiap fungsi Composable harus mandiri pada level posisinya di pohon UI.
Aturan ketiga — larangan efek samping di dalam tubuh fungsi Composable. Operasi seperti menulis ke basis data, mengirim permintaan jaringan, atau mengubah variabel eksternal hanya boleh dilakukan di dalam efek khusus LaunchedEffect, DisposableEffect, atau SideEffect. Pelanggaran aturan ini menyebabkan perilaku yang tidak dapat diprediksi saat rekomposisi.
Aturan keempat: fungsi Composable harus idempoten. Pemanggilan ulang dengan argumen yang sama harus menghasilkan UI yang sama. Persyaratan ini diperlukan untuk kerja optimalisasi skipping yang benar, di mana Compose melewatkan penggambaran ulang fungsi yang data masukannya tidak berubah.
// Benar: fungsi Composable murni tanpa efek samping
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
Card(modifier = Modifier.clickable { onClick() }) {
Text(text = user.name)
}
}
// Salah: efek samping di dalam tubuh
@Composable
fun WrongCard(userId: String) {
// val result = viewModel.loadUser(userId) // TIDAK DIIZINKAN
Text("Memuat...")
}
Mari kita lihat contoh praktis pembuatan layar profil menggunakan anotasi @Composable. Di sini kami mendemonstrasikan penggabungan beberapa fungsi Composable, bekerja dengan status dan pengubah — elemen kunci dari setiap tata letak Compose.
@Composable
fun ProfileScreen(userId: String) {
var isFollowed by remember { mutableStateOf(false) }
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
ProfileHeader(userId = userId)
Spacer(modifier = Modifier.height(16.dp))
StatsRow(posts = 42, followers = 1280)
Spacer(modifier = Modifier.height(24.dp))
FollowButton(
isFollowed = isFollowed,
onToggle = { isFollowed = !isFollowed }
)
}
}
@Composable
fun ProfileHeader(userId: String) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(model = "https://example.com/avatars/$userId",
contentDescription = "User avatar")
Spacer(modifier = Modifier.width(12.dp))
Text(text = "Pengguna #$userId", style = MaterialTheme.typography.headlineMedium)
}
}
@Composable
fun StatsRow(posts: Int, followers: Int) {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
StatItem("Posts", posts)
StatItem("Followers", followers)
}
}
@Composable
fun StatItem(label: String, value: Int) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "$value", style = MaterialTheme.typography.headlineSmall)
Text(text = label, style = MaterialTheme.typography.bodySmall)
}
}
Dalam contoh, setiap fungsi Composable bertanggung jawab atas bagian layarnya: ProfileScreen mengelola status umum dan komposisi fungsi anak, ProfileHeader menampilkan avatar dan nama, dan StatsRow — blok dengan statistik. Pendekatan ini mengikuti prinsip tanggung jawab tunggal dan menyederhanakan penggunaan ulang komponen.
Di Jetpack Compose ada tiga jenis utama fungsi Composable. Jenis pertama — wadah (Row, Column, Box, LazyColumn) yang menentukan penempatan elemen anak. Kedua — elemen tampilan (Text, Image, Icon, Button) yang me-render komponen UI tertentu. Ketiga — fungsi Composable kustom yang menggabungkan komponen bawaan ke dalam blok yang dapat digunakan kembali.
Wadah berbeda dari elemen biasa karena mereka menerima lambda content — parameter terakhir bertipe @Composable () -> Unit. Mekanisme inilah yang memungkinkan pembangunan pohon UI bersarang: setiap wadah menciptakan komposisi anak dengan konteks dan area memorinya sendiri.
Fungsi Composable kustom dibagi menjadi dua subtipe: cerdas (smart) dan dungu (dumb). Fungsi cerdas mengelola status dan logika — berisi panggilan ke remember, LaunchedEffect, dan API Compose lainnya. Fungsi dungu menerima semua data melalui parameter dan hanya menampilkannya. Pembagian menjadi komponen cerdas dan dungu meningkatkan kemampuan pengujian dan penggunaan ulang kode.
| Jenis | Contoh | Tujuan |
|---|---|---|
| Wadah | Column, Row, Box | Mengelola penempatan elemen anak |
| Elemen | Text, Image, Button | Menampilkan konten dan memproses masukan |
| Kustom | ProfileCard, UserList | Kombinasi komponen standar |
Keuntungan utama anotasi @Composable — kemampuan untuk membuat komponen UI yang dapat digunakan kembali tanpa pewarisan dan hierarki kelas yang kompleks. Berbeda dengan sistem View, di mana setiap elemen kustom memerlukan pembuatan kelas Java dengan konstruktor, komponen Composable hanyalah fungsi Kotlin dengan parameter.
Untuk memastikan penggunaan ulang, diterapkan pola Slot API, di mana fungsi Composable menerima lambda content untuk berbagai area tata letaknya. Misalnya, komponen Card dapat menerima content terpisah untuk header, body, dan bagian bawah, membuatnya universal untuk layar aplikasi apa pun.
Pengubah (Modifier) memainkan peran kunci dalam penggunaan ulang: mereka memungkinkan penyesuaian jarak, ukuran, klik, dan animasi tanpa mengubah komponen itu sendiri. Disarankan untuk selalu meneruskan Modifier sebagai parameter fungsi Composable dengan nilai default: Modifier = Modifier — ini adalah praktik standar yang diadopsi di pustaka resmi Google.
@Composable
fun SectionCard(
modifier: Modifier = Modifier,
title: String,
content: @Composable () -> Unit
) {
Card(modifier = modifier) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = title, style = MaterialTheme.typography.titleMedium)
Spacer(modifier = Modifier.height(8.dp))
content()
}
}
}
Berkat Slot API, komponen SectionCard dapat digunakan di berbagai layar dengan konten berbeda — formulir, daftar, blok teks. Kombinasi pengubah dan Slot API membuat komponen Compose sangat fleksibel tanpa kehilangan keamanan tipe yang disediakan Kotlin.
Pertanyaan yang Sering Diajukan
Fungsi @Composable dijalankan dalam konteks komposisi dan dapat membaca status, secara otomatis dimulai ulang saat berubah. Fungsi Kotlin biasa tidak memiliki akses ke mekanisme pelacakan status dan tidak berpartisipasi dalam pembangunan pohon UI.
Tidak, fungsi Composable hanya dapat dipanggil dari fungsi Composable lain, karena diperlukan konteks komposisi khusus. Untuk integrasi kode Compose dengan Kotlin biasa, digunakan metode setContent { } di Activity atau ComposeView di sistem View.
Ini adalah konvensi penamaan yang diadopsi di komunitas Compose. Huruf kapital membedakan komponen UI dari fungsi biasa secara visual, mengikuti aturan penamaan kelas. Ini bukan persyaratan kompiler, tetapi praktik yang direkomendasikan dalam dokumentasi Google.
Tidak ada batasan jumlah. Dalam praktiknya, layar besar dapat berisi 50–100 fungsi Composable, termasuk komponen bawaan (Text, Button) dan kustom. Compose mengoptimalkan pohon fungsi dan hanya menjalankan yang data masukannya berubah.
Biasanya fungsi Composable mengembalikan Unit, karena tugas mereka adalah membangun UI. Namun ada fungsi khusus seperti remember dan derivedStateOf yang ditandai dengan @Composable dan mengembalikan nilai. Ini adalah pengecualian, bukan aturan.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga