@Composable anotasyonu, Jetpack Compose'un temel bir öğesidir ve sıradan bir Kotlin fonksiyonunu bildirimsel bir kullanıcı arayüzü yapı taşına dönüştürür. Bu anotasyon olmadan, modern Android geliştirmede herhangi bir ekran oluşturmak imkansızdır. Google Android Developers, 2026'ya göre, yeni Kotlin projelerinin %80'inden fazlası UI oluşturmak için Compose kullanıyor ve @Composable ekosistemde en sık kullanılan anotasyondur.
Önemli Noktalar
@Composable, Kotlin dilinin bir anotasyonudur ve bir fonksiyonu Jetpack Compose çerçevesinde kullanıcı arayüzünü tanımlamak için işaretler. Kotlin derleyicisi bu anotasyonla karşılaştığında, fonksiyonun kompozisyon bağlamında — UI ağacı yönetim sistemi — çalışmasını sağlayan ek kod üretir.
@Composable anotasyonu, Google tarafından 2021 yılında Jetpack Compose 1.0'ın ilk kararlı sürümüyle birlikte tanıtıldı. Ortaya çıkışından önce, Android arayüz geliştirmesi yalnızca XML işaretlemesi ve View sistemi üzerinden yapılıyordu. @Composable yaklaşımı kökten değiştirdi: UI'yı ayrı bir işaretleme dosyasında tanımlamak yerine, geliştirici arayüzü doğrudan Kotlin'de yazıyor.
@Composable ile sıradan Kotlin fonksiyonları arasındaki temel fark, durumu okuma ve değişikliklerine tepki verme yeteneğidir. Bir Composable fonksiyonun okuduğu bir değişken değerini değiştirdiğinde, sistem otomatik olarak bu fonksiyonun yeniden başlatılmasını (yeniden kompozisyon) planlar. Bu, geliştiriciyi findViewById ve setText aracılığıyla manuel UI güncellemesinden kurtarır.
@Composable'ın iç mekaniği, slot kavramına dayanır — kompozisyon içindeki her fonksiyon için ayrılan özel bir bellek alanı. Bu slot, fonksiyona iletilen değerleri ve sonraki çağrılarda karşılaştırma için gerekli hizmet bilgilerini saklar.
Bir Composable fonksiyon bildirmek için, fun anahtar sözcüğünden önce @Composable anotasyonunu eklemek yeterlidir. Fonksiyon, anotasyonu androidx.compose.runtime'dan içe aktaran bir pakette bulunmalıdır. Fonksiyon adının büyük harfle başlatılması önerilir — bu, Compose topluluğunda yaygın olarak kabul edilen ve UI bileşenlerini sıradan fonksiyonlardan görsel olarak ayıran bir kuraldır.
import androidx.compose.runtime.Composable
@Composable
fun Greeting(name: String) {
var count by remember { mutableStateOf(0) }
Column {
Text("Merhaba, $name!")
Button(onClick = { count++ }) {
Text("$count kez tıklandı")
}
}
}
Bir Composable fonksiyonun parametreleri herhangi bir şey olabilir — ilkel türler, dizeler, lambdalar ve hatta Slot API aracılığıyla iletilen diğer Composable fonksiyonlar. Önerilen, yeniden kompozisyon sırasında yan etkileri önlemek için parametrelerin değişmez (val) yapılmasıdır. Tüm değişebilir veriler, Compose durum mekanizmaları aracılığıyla yönetilmelidir.
Composable fonksiyonlar, normal fonksiyonlar gibi rastgele değerler döndüremez — tek görevleri UI ağacının bir parçasını oluşturmak veya güncellemektir. Ancak, State Hoisting gibi özel desenler vardır; burada bir Compose fonksiyonu parametreler aracılığıyla durum ve geri çağrımları kabul eder, saf ve yeniden kullanılabilir kalır.
Compose sistemi, Composable fonksiyonların nasıl görünmesi ve davranması gerektiği konusunda birkaç katı kısıtlama getirir. İlk kural: Bir Composable fonksiyon yalnızca diğer Composable fonksiyonları veya yan etkisi olmayan normal fonksiyonları çağırabilir. Bu, kompozisyonun öngörülebilirliğini ve Compose optimizasyonlarının doğru çalışmasını sağlar.
İkinci kural, yürütme sırasıyla ilgilidir. Compose, Composable fonksiyonları herhangi bir sırada çağırma hakkına sahiptir, bu nedenle böyle bir fonksiyonun gövdesindeki kod, komşu fonksiyonların çağrılma sırasına bağlı olmamalıdır. Her Composable fonksiyon, UI ağacındaki konumu düzeyinde kendi kendine yeterli olmalıdır.
Üçüncü kural — bir Composable fonksiyonun gövdesi içinde yan etkilerin yasaklanması. Veritabanına yazma, ağ istekleri gönderme veya dış değişkenleri değiştirme gibi işlemler yalnızca özel efektler içinde yapılmalıdır: LaunchedEffect, DisposableEffect veya SideEffect. Bu kuralı ihlal etmek, yeniden kompozisyonlar sırasında öngörülemeyen davranışlara yol açar.
Dördüncü kural: Composable fonksiyonlar eşgüçlü (idempotent) olmalıdır. Aynı argümanlarla tekrar çağırmak, aynı UI'yı üretmelidir. Bu gereklilik, giriş verileri değişmeyen fonksiyonların yeniden çizimini Compose'un atladığı atlama optimizasyonunun doğru çalışması için gereklidir.
// Doğru: yan etkisiz saf Composable fonksiyon
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
Card(modifier = Modifier.clickable { onClick() }) {
Text(text = user.name)
}
}
// Yanlış: gövde içinde yan etki
@Composable
fun WrongCard(userId: String) {
// val result = viewModel.loadUser(userId) // İZİN VERİLMEDİ
Text("Yükleniyor...")
}
@Composable anotasyonunu kullanarak bir profil ekranı oluşturmanın pratik bir örneğine bakalım. Burada, birden çok Composable fonksiyonun birleşimini, durum ve değiştiricilerle çalışmayı gösteriyoruz — herhangi bir Compose düzeninin temel öğeleri.
@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 = "Kullanıcı #$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)
}
}
Örnekte, her Composable fonksiyon ekranın kendi bölümünden sorumludur: ProfileScreen genel durumu ve alt fonksiyonların kompozisyonunu yönetir, ProfileHeader avatarı ve adı görüntüler, StatsRow ise bir istatistik bloğu gösterir. Bu yaklaşım, tek sorumluluk ilkesini izler ve bileşen yeniden kullanımını basitleştirir.
Jetpack Compose'ta üç ana Composable fonksiyon türü vardır. İlk tür — kapsayıcılar (Row, Column, Box, LazyColumn) — alt öğelerin düzenini belirler. İkinci tür — görüntüleme öğeleri (Text, Image, Icon, Button) — belirli UI bileşenlerini işler. Üçüncü tür — özel Composable fonksiyonlar — yerleşik bileşenleri yeniden kullanılabilir bloklarda birleştirir.
Kapsayıcılar, normal öğelerden bir content lambda'sını kabul etmeleriyle ayrılır — @Composable () -> Unit türündeki son parametre. Bu mekanizma, iç içe UI ağaçları oluşturmaya olanak tanır: her kapsayıcı, kendi bağlamı ve bellek alanıyla bir alt kompozisyon oluşturur.
Özel Composable fonksiyonlar iki alt türe ayrılır: akıllı (smart) ve basit (dumb). Akıllı fonksiyonlar durumu ve mantığı yönetir — remember, LaunchedEffect ve diğer Compose API'lerine çağrılar içerir. Basit fonksiyonlar tüm verileri parametreler aracılığıyla alır ve yalnızca görüntüler. Akıllı ve basit bileşenlere ayırma, test edilebilirliği ve kod yeniden kullanımını iyileştirir.
| Tür | Örnek | Amaç |
|---|---|---|
| Kapsayıcı | Column, Row, Box | Alt öğelerin düzenini yönetme |
| Öğe | Text, Image, Button | İçeriği görüntüleme ve girdi işleme |
| Özel | ProfileCard, UserList | Standart bileşenlerin birleştirilmesi |
@Composable anotasyonunun ana avantajı, kalıtım ve karmaşık sınıf hiyerarşileri olmadan yeniden kullanılabilir UI bileşenleri oluşturma yeteneğidir. Her özel öğenin yapıcılarla bir Java sınıfı oluşturmayı gerektirdiği View sisteminin aksine, bir Composable bileşen yalnızca parametrelere sahip bir Kotlin fonksiyonudur.
Yeniden kullanılabilirliği sağlamak için Slot API deseni kullanılır; burada bir Composable fonksiyon, düzeninin farklı alanları için content lambdalarını kabul eder. Örneğin, bir Card bileşeni, başlık, gövde ve alt bilgi için ayrı içerikler kabul edebilir ve bu da onu uygulamanın herhangi bir ekranı için evrensel hale getirir.
Değiştiriciler (Modifier), yeniden kullanılabilirlikte anahtar bir rol oynar: bileşenin kendisini değiştirmeden dolgu, boyut, tıklama ve animasyonları yapılandırmaya izin verir. Varsayılan bir değerle (Modifier = Modifier) Composable fonksiyonun bir parametresi olarak her zaman Modifier iletilmesi önerilir — bu, Google'ın resmi kütüphanelerinde benimsenen standart bir uygulamadır.
@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()
}
}
}
Slot API sayesinde, SectionCard bileşeni farklı içeriklerle (formlar, listeler, metin blokları) farklı ekranlarda kullanılabilir. Değiştiriciler ve Slot API'nin birleşimi, Kotlin'in sağladığı tür güvenliğini kaybetmeden Compose bileşenlerini son derece esnek hale getirir.
Sıkça Sorulan Sorular
@Composable fonksiyonu kompozisyon bağlamında yürütülür ve durumu okuyabilir, değiştiğinde otomatik olarak yeniden başlatılır. Normal Kotlin fonksiyonları, durum izleme mekanizmalarına erişime sahip değildir ve UI ağacının oluşturulmasına katılmaz.
Hayır, Composable fonksiyonlar yalnızca diğer Composable fonksiyonlardan çağrılabilir, çünkü özel bir kompozisyon bağlamı gerekir. Compose kodunu normal Kotlin ile entegre etmek için Activity'de setContent { } yöntemi veya View sisteminde ComposeView kullanılır.
Bu, Compose topluluğunda benimsenen bir adlandırma kuralıdır. Büyük harf, UI bileşenlerini sıradan fonksiyonlardan görsel olarak ayırır ve sınıf adlandırma kurallarını izler. Bu bir derleyici gereksinimi değil, Google dokümantasyonunda önerilen bir uygulamadır.
Sayıyla ilgili bir sınırlama yoktur. Pratikte, büyük bir ekran, yerleşik bileşenler (Text, Button) ve özel bileşenler dahil olmak üzere 50–100 Composable fonksiyon içerebilir. Compose, fonksiyon ağacını optimize eder ve yalnızca giriş verileri değişenleri yürütür.
Genellikle Composable fonksiyonlar Unit döndürür, çünkü görevleri UI oluşturmaktır. Ancak, @Composable ile işaretlenmiş ve değer döndüren remember ve derivedStateOf gibi özelleşmiş fonksiyonlar vardır. Bu bir istisnadır, kural değil.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun