mutableStateOf, Jetpack Compose'da değiştirilebilir gözlemlenebilir durum kapsayıcısı oluşturan bir işlevdir. Bu kapsayıcının içindeki değer değiştiğinde, Compose bu durumu okuyan tüm bileşenlerin yeniden oluşturulmasını otomatik olarak tetikler. mutableStateOf olmadan, veriler değiştiğinde UI tepkisel olarak güncellenemezdi. Google Android Developers, 2026'ya göre mutableStateOf, Compose'da yerel durum için ana yapı taşıdır.
Önemli Noktalar
mutableStateOf, compose.runtime paketinden bir işlevdir ve bir değer depolayan ve Compose Runtime'ı değişiklikler hakkında bilgilendirebilen bir MutableState<T> nesnesi oluşturur. İmza: fun <T> mutableStateOf(value: T, policy: SnapshotMutationPolicy<T> = structuralEquality()): MutableState<T>. policy parametresi, bir değişikliğin ne zaman önemli kabul edileceğini belirler — yapısal eşitlikte, referans eşitliğinde veya asla.
MutableState, tek bir value özelliğine sahip bir arayüzdür: okuma için bir getter ve yazma için bir setter. Setter çağrıldığında, Compose Runtime değişikliği bir snapshot'a kaydeder ve bu State değişkenini okuyan tüm Composable işlevlerini yeniden oluşturma gerektiriyor olarak işaretler. Bu işlem, tek bir snapshot döngüsü içinde senkron olarak gerçekleşir ve kademeli değişiklikler sırasında ara durumları ortadan kaldırır.
policy parametresi — mutableStateOf'un ikinci argümanı, karşılaştırma davranışını tanımlar. structuralEquality() equals() işlevini kontrol eder — bu varsayılan davranıştır. referentialEquality() === (referans eşitliği) kontrol eder. neverEqual() her atamayı bir değişiklik olarak kabul eder. policy seçimi, aynı değer atandığında yeniden oluşturmanın tetiklenip tetiklenmeyeceğini etkiler.
Gözlemlenebilir durum bildirmenin en basit yolu, mutableStateOf'u remember ile kullanmaktır. remember olmadan, her yeniden oluşturma yeni bir State oluşturur ve önceki tüm değişiklikler kaybolurdu. remember, Composable işlevi kompozisyonda kaldığı sürece aynı MutableState'in bir dizi yeniden oluşturma boyunca hayatta kalmasını sağlar.
@Composable
fun Counter() {
// Yetkilendirme yok: .value ile okuma/yazma
val count = remember { mutableStateOf(0) }
Button(onClick = { count.value++ }) {
Text("Count: ${count.value}")
}
}
@Composable
fun CounterDelegated() {
// Yetkilendirme var: var + by = Property Delegation
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Count: $count")
}
}
İki yaklaşım arasındaki fark sözdizimseldir. Property Delegation (by), bir Kotlin kuralı kullanır: derleyici, okuma ve yazma için getValue() ve setValue() çağrıları üretir. Bu, count.value'ya doğrudan erişmeye eşdeğerdir ancak normal bir değişkenle çalışıyormuş gibi görünür. Her iki yaklaşım da işlevsel olarak aynıdır: Compose, gösterimden bağımsız olarak getter'daki okumayı ve setter'daki yazmayı izler.
| Biçim | Kod | Okuma | Yazma |
|---|---|---|---|
| Yetkilendirme yok | val count = mutableStateOf(0) | count.value | count.value = n |
| Yetkilendirme var | var count by mutableStateOf(0) | count | count = n |
Kotlin'in yetkilendirilmiş özellik mekanizması, Compose'un bir özelliği değil, dilin yerleşik bir yeteneğidir. Herhangi bir sınıf, getValue(thisRef, property) ve setValue(thisRef, property, value) operatörlerini uygulayabilir, ardından örneği by anahtar sözcüğüyle kullanılabilir. MutableState tam olarak bu şekilde çalışır: getValue geçerli değeri döndürür ve setValue yeni bir değer atar.
Önemli bir ayrım: val vs var. mutableStateOf hem val hem de var'a atanabilir. val (val count = mutableStateOf(0)) ile MutableState nesnesinin kendisi değişmezdir, ancak value özelliği değiştirilebilir. var (var count by mutableStateOf(0)) ile yetkilendirme, bir ilkel türle çalışma yanılsaması yaratır, ancak setter aslında MutableState üzerinde setValue'yu çağırır. val ve var arasında seçim yapmak, .value'ya açık ve örtük erişim arasında seçim yapmaktır.
State Yetkilendirmesi, kodu basitleştiren ancak mekaniği değiştirmeyen sözdizimsel şekerdir. Kotlin derleyicisi, var x by mutableStateOf(0) ifadesini mutableStateOf.getValue() ve mutableStateOf.setValue() işlevlerini çağıran getter/setter'a dönüştürür. Oluşturulan bayt kodunda, by ile val ve var arasında hiçbir fark yoktur — her ikisi de aynı MutableState kapsayıcısı aracılığıyla çalışır.
// Compose State için özel yetkili
class ValidatedState<T>(initialValue: T) {
private val state = mutableStateOf(initialValue)
operator fun getValue(thisRef: Any?, property: KProperty<*>) = state.value
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
if (value != state.value) {
state.value = value
}
}
}
@Composable
fun Test() {
var text by remember { ValidatedState("") }
}
Snapshot, paralel değişiklikler sırasında State okuma tutarlılığını sağlayan bir Compose Runtime mekanizmasıdır. Bir Composable işlevi mutableStateOf'u okuduğunda, snapshot geçerli değeri kaydeder. Kompozisyon sırasında başka bir değişiklik aynı State'e yazarsa, snapshot yazmayı görür ancak tutarsız verilerin okunmasına izin vermez — okuma her zaman snapshot başlangıcında geçerli olan değeri döndürür.
Setter mutableStateOf.value = newValue çağrıldığında, Compose Runtime hemen yeniden oluşturmayı tetiklemez. Bunun yerine, değişiklik geçerli snapshot'a kaydedilir. Snapshot uygulandığında (çerçeve sınırında), Compose değiştirilen State'lerin listesini tarar ve okuyan bileşenleri Invalid olarak işaretler. Yalnızca bir sonraki çerçevede yeniden oluşturma başlar. Bu, kademeli değişiklikler sırasında UI'nin onlarca kez yeniden çizilmemesini garanti eder.
Küresel ve yerel snapshot'lar: varsayılan olarak, mutableStateOf otomatik olarak uygulanan küresel snapshot'ta çalışır. Snapshot.takeSnapshot() aracılığıyla yan etkiler olmadan yalıtılmış okuma için yerel bir snapshot oluşturabilirsiniz. Bu, değişikliklere abone olmadan State'i okumanız gerektiğinde Modifier içinde kullanılır. Bu yaklaşım performansı optimize eder ve beklenmeyen yeniden oluşturmaları önler.
Gerçek bir senaryo düşünelim — üç alanlı bir giriş formu: e-posta, şifre ve yükleme durumu. Her üç alan da mutableStateOf kullanır, ancak farklı policy'ler ve farklı iç içe geçme seviyeleriyle. e-posta yetkilendirme kullanır, şifre doğrudan erişim kullanır.
data class LoginState(
val email: String = "",
val password: String = "",
val isLoading: Boolean = false,
val error: String? = null
)
@Composable
fun LoginForm(onLogin: (String, String) -> Unit) {
// Form için tek State, policy = referentialEquality
var formState by remember {
mutableStateOf(LoginState(), SnapshotMutationPolicy.referentialEquality())
}
val isValid = remember(formState) {
formState.email.contains("@") && formState.password.length() >= 6
}
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = formState.email,
onValueChange = { formState = formState.copy(email = it) },
label = { Text("E-posta") }
)
OutlinedTextField(
value = formState.password,
onValueChange = { formState = formState.copy(password = it) },
label = { Text("Şifre") },
visualTransformation = PasswordVisualTransformation()
)
Button(
onClick = { onLogin(formState.email, formState.password) },
enabled = isValid
) {
Text("Giriş yap")
}
}
}
Bu örnekte, mutableStateOf özel bir veri sınıfı olan LoginState ve policy referentialEquality ile kullanılır. Bu, yeniden oluşturmanın yalnızca copy() aracılığıyla yeni bir LoginState örneği atandığında tetikleneceği anlamına gelir. isValid, formState'e göre hesaplanır ve yalnızca değiştiğinde yeniden hesaplanır. Bu yaklaşım, yeniden oluşturmalar üzerinde net kontrol sağlar: her form alanı yalnızca yeni bir kopya oluşturularak değişir.
Sıkça Sorulan Sorular
mutableStateOf, snapshot'lar içinde çalışan Compose'a özgü bir kapsayıcıdır. StateFlow, kotlinx.coroutines.flow'dan gelir ve Compose'a bağlı değildir. mutableStateOf otomatik olarak yeniden oluşturmayı tetiklerken, StateFlow collectAsState() gerektirir. Composable içindeki UI durumu için mutableStateOf tercih edilir.
Evet, mutableStateOf Composable işlevlerinin dışında çağrılabilir, ancak izlenmez. UI'da tepkisellik için State'in Composable içinde okunması gerekir. Birçok ViewModel, StateFlow aracılığıyla UI'ya durum iletmek için MutableStateField'ı (mutableStateOf etrafında bir sarmalayıcı) kullanır.
Snapshot sistemi tutarlılığı garanti eder: her yeniden oluşturma, snapshot başlangıcında tutarlı bir durum görür. Farklı iş parçacıklarından gelen değişiklikler çerçeve sınırında atomik olarak uygulanır ve tek bir kompozisyon içindeki okumalar sırasında yarış koşullarını ortadan kaldırır.
Yeni bir değer atayın: count.value = 0 (veya yetkilendirme ile count = 0). State'i tamamen yeniden oluşturmanız gerekiyorsa, bir anahtarla remember kullanın: remember(key) { mutableStateOf(initial) } — anahtar değiştiğinde State yeniden oluşturulur.
Composer, değişiklikleri gruplayan snapshot'lar kullanır: tek bir çerçevede yüzlerce atama olsa bile yeniden oluşturma yalnızca bir kez çalışır. Çok sık güncellemeler (animasyonlar) için Animatable veya animate*AsState kullanın — bunlar kare tabanlı güncellemeler için optimize edilmiştir.
Ö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