MutableState — Compose'da gözlemlenebilir durum ve güncelleme mekanizması

Yazar: IT Sectr Yayınlanma: 2026-06-28 Okuma süresi: 7 dk

MutableState, Jetpack Compose'da değiştirilebilir gözlemlenebilir bir değer için kapsayıcıyı temsil eden bir arayüzdür. Compose'un tepkisel sisteminin temelidir: MutableState değeri setter aracılığıyla her değiştiğinde, Compose Runtime tüm okuyan bileşenlere bildirim gönderir ve yeniden oluşturmayı başlatır. Google Android Developers, 2026'ya göre, bildirimsel bir UI'da durumla doğru çalışmak için MutableState'i anlamak zorunludur.

Önemli noktalar

  • MutableState — tek bir value özelliğine sahip compose.runtime arayüzü (getter + setter)
  • State — salt okunur üst arayüz, MutableState yazma yeteneği ekler
  • Yeniden oluşturma, aktif bir snapshot döngüsü içinde value setter'ı çağrıldığında tetiklenir
  • SnapshotMutationPolicy, bir değişikliğin yeniden oluşturma için ne zaman önemli kabul edildiğini belirler
  • MutableIntState ve benzerleri — MutableState'in optimize edilmiş ilkel sürümleri

Jetpack Compose'da MutableState nedir

MutableState, androidx.compose.runtime paketinden tek bir özellik bildiren bir arayüzdür: override var value: T. Getter mevcut değeri döndürür, setter yeni bir değer yazar ve Compose Runtime'a değişikliği bildirir. Arayüz, value'nun salt okunur olduğu State<T>'den miras alır. Bu iki seviyeli mimari, erişim ayrımına izin verir: yalnızca değeri okuması gereken bir bileşen State<T> alırken, sahip bileşen MutableState<T> alır.

MutableState'in varsayılan uygulaması, değişiklikleri izlemek için bir snapshot mekanizması kullanan iç sınıf SnapshotMutableStateImpl'dir. Value setter'ı çağrıldığında, geçerli snapshot yazmayı kaydeder ve kayıtlı tüm ObservedScope'ları geçersiz olarak işaretler. Bu kapsamlar (genellikle Composable işlevleri) sonraki karede yeniden oluşturulacaktır. Lock-free snapshot mimarisi sayesinde tüm süreç eşzamanlı ve kilit olmadan gerçekleşir.

State vs MutableState: State, bileşenlerin genel API'leri için kullanılan salt okunur bir arayüzdür. Bir Composable işlev parametresini State<Int> olarak bildirdiğinizde, bileşenin durumu okuyabileceğini ancak değiştiremeyeceğini garanti edersiniz. MutableState, sahip bileşen içinde kullanılır. Bu ayrım, yetkisiz değişiklikleri önleyen temel Compose uygulamalarından biridir.

State, MutableState ve türetilmiş arayüzlerin hiyerarşisi

Compose'daki durum arayüzleri hiyerarşisinin birkaç seviyesi vardır. En üstte salt okunur value'ya sahip State<T> bulunur. Altında okuma-yazma value'ya sahip MutableState<T> bulunur. Daha aşağıda, ilkel boxing'den kaçınan özelleşmiş ilkel sürümler gelir: MutableIntState, MutableFloatState, MutableLongState, MutableBooleanState ve diğerleri.

MutableDoubleState ve MutableLongState daha az yaygındır ancak mevcuttur. Koleksiyon arayüzleri: MutableListState — bir liste içindeki değişiklikleri izlemek için, MutableStateMap — haritalar için. Bu arayüzlerin her biri belirli bir senaryo için optimize edilmiştir ve temel MutableState'i ek koleksiyon işleme yöntemleriyle genişletir.

SnapshotStateList ve SnapshotStateMap, snapshot'larla uyumlu değiştirilebilir liste ve haritaların uygulamalarıdır. Yalnızca değer değiştirmeyi değil, aynı zamanda iç değişiklikleri de izlemeye izin verirler: listeye öğe ekleme, silme, mevcut bir öğeyi değiştirme. Bu tür yapılar için, mutableStateListOf() ve mutableStateMapOf() ilgili gözlemlenebilir koleksiyonları oluşturur.

ArayüzAmaçOluşturma yöntemi
State<T>Salt okunur kapsayıcı
MutableState<T>Okuma-yazma kapsayıcımutableStateOf()
MutableIntStateBoxing olmadan ilkel IntmutableIntStateOf()
MutableFloatStateBoxing olmadan ilkel FloatmutableFloatStateOf()
SnapshotStateListGözlemlenebilir listemutableStateListOf()
SnapshotStateMapGözlemlenebilir haritamutableStateMapOf()

SnapshotMutationPolicy: yeniden oluşturma ne zaman tetiklenir

SnapshotMutationPolicy, MutableState'deki bir değişikliğin ne zaman önemli kabul edildiğini belirleyen bir arayüzdür. mutableStateOf, ikinci argüman olarak policy'yi kabul eder. Standart uygulamalar: structuralEquality() (equals), referentialEquality() (===), neverEqualPolicy() (değişikliği her zaman önemli kabul eder). Özel mantık için kendi politikanızı uygulayabilirsiniz.

structuralEquality() — varsayılan davranış. Compose, yeni değeri eskisiyle equals() aracılığıyla karşılaştırır. Sonuç true ise, yeniden oluşturma TETİKLENMEZ. Bu, aynı alanlara sahip iki örneğin eşit kabul edildiği ilkeller ve data class'lar için kullanışlıdır. Sorun: bir data class bir List içeriyorsa, equals() derin bir karşılaştırma yapar ve bu büyük listeler için maliyetli olabilir.

referentialEquality() — === aracılığıyla referansları karşılaştırır. Yeniden oluşturma, içerik aynı olsa bile yalnızca farklı bir nesne atandığında tetiklenir. Bu, her yeni örneğin bir değişikliği garanti ettiği değiştirilemez data class'lar için idealdir. neverEqualPolicy() — karşılaştırma yapmadan değişikliği her zaman önemli kabul eder. Setter'ın nadiren çağrıldığı ve equals için zaman harcamaya gerek olmadığı durumlarda kullanışlıdır.

kotlin
    // Policy comparison in practice
data class User(val name: String, val age: Int)

@Composable
fun UserProfile() {
    // structuralEquality: recomposition ONLY if data changed
    var user1 by remember {
        mutableStateOf(User("Alice", 30))
    }

    // referentialEquality: recomposition on ANY assignment
    var user2 by remember {
        mutableStateOf(User("Bob", 25),
            SnapshotMutationPolicy.referentialEquality())
    }

    // user1: copy() with same fields does NOT trigger recomposition
    // user2: even user2.copy() == user2 triggers recomposition (new ref)
}

İlkel State: MutableIntState, MutableFloatState, MutableLongState

İlkel MutableIntState ve benzerleri, boxing olmadan ilkelleri depolayan özelleşmiş arayüzlerdir. Normal bir MutableState<Int>, Int'i Integer olarak depolar ve her yazmada yığında bir nesne oluşturur. MutableIntState, int (ilkel) depolar ve boxing yükünü tamamen ortadan kaldırır. Bu, yüksek frekanslı güncellemeler için özellikle önemlidir — sayaçlar, kaydırma konumları, animasyon değerleri.

mutableIntStateOf(), mutableFloatStateOf(), mutableLongStateOf() — ilkel MutableState oluşturan işlevler. Arayüzler MutableIntState, MutableFloatState, MutableLongState olarak adlandırılır. Sırasıyla MutableState<Int>, MutableState<Float> ve MutableState<Long>’i genişletir ve ilkel hızlı erişim için intValue özelliğini ekler. İç uygulamaları, kilitsiz okuma/yazma için AtomicInteger kullanır.

Kullanım: sayaçlar (Int), kaydırma konumları (Float offset), zaman damgaları (Long). Çoğu günlük senaryoda performans farkı fark edilmez, ancak binlerce öğe ve geçiş animasyonuna sahip LazyList'te ilkel State, belirgin bir iyileştirme sağlar. Google, evrensel mutableStateOf yerine tipik senaryolar için ilkel State kullanılmasını önerir.

kotlin
@Composable
fun ScrollCounter() {
    // Bad: boxing on every update
    var badCount by remember { mutableStateOf(0) }

    // Good: no boxing, primitive storage
    var goodCount by remember { mutableIntStateOf(0) }

    // Usage is identical
    Button(onClick = { goodCount++ }) {
        Text("Count: $goodCount")
    }
}

MutableState ile çalışma örnekleri

Bir TodoList bileşenini düşünün. Burada MutableState iki biçimde kullanılır: giriş durumu için ayrı değişkenler ve dinamik bir görev listesi için SnapshotStateList olarak. Her ikisi de kod kısalığı için yetkilendirme kullanır.

kotlin
data class TodoItem(val id: Int, val text: String, val isDone: Boolean = false)

@Composable
fun TodoScreen() {
    var inputText by remember { mutableStateOf("") }
    val items = remember { mutableStateListOf() }

    Column(modifier = Modifier.padding(16.dp)) {
        Row {
            TextField(
                value = inputText,
                onValueChange = { inputText = it }
            )
            Button(onClick = {
                if (inputText.isNotBlank()) {
                    items.add(TodoItem(items.size, inputText))
                    inputText = ""
                }
            }) { Text("Add") }
        }

        LazyColumn {
            items(items) { item ->
                Row(modifier = Modifier.fillMaxWidth().clickable {
                    val idx = items.indexOf(item)
                    items[idx] = item.copy(isDone = !item.isDone)
                }) {
                    Checkbox(checked = item.isDone, onCheckedChange = null)
                    Text(item.text)
                }
            }
        }
    }
}

mutableStateListOf bir SnapshotStateList oluşturur — tek tek öğelerdeki değişiklikleri izleyen değiştirilebilir bir liste. items.add() ve items[n] = newValue çağrıldığında, Compose mutasyonu görür ve yalnızca değişen LazyColumn öğelerini yeniden oluşturur. inputText, normal bir MutableState<String>’dir. İki MutableState türünün (tek ve koleksiyon) kombinasyonu, formlar ve listeler içeren ekranlar için tipik bir kalıptır.

Sıkça sorulan sorular

MutableState'i remember olmadan kullanabilir miyim?

MutableState remember olmadan her yeniden oluşturmada yeniden oluşturulur. mutableStateOf'a yapılan her yeni çağrı yeni bir nesne oluşturur ve eski değer kaybolur. State, Composable dışında (örneğin ViewModel'de) oluşturulmadıkça, yeniden oluşturmalar arasında State'i korumak için her zaman remember kullanın.

MutableState normal bir değişkene nasıl dönüştürülür?

Snapshot { } aracılığıyla bir snapshot dışında .value'yu bir kez okuyun. Ancak bu tepkiselliği devre dışı bırakır — değişiklikler artık yeniden oluşturmayı tetiklemez. Abonelik olmadan tek seferlik okuma için, okuma yapmadan bir snapshot içinde currentValue() kullanın.

Hangisi daha hızlı: mutableStateOf mu mutableIntStateOf mu?

mutableIntStateOf daha hızlıdır çünkü int'i Integer'a boxing yapmayı gerektirmez. Saniyede binlerce güncelleme (animasyon, kaydırma) ile fark, ayırma süresinde %30-50'ye ulaşabilir. Seyrek güncellemeler (tıklamalar, metin girişi) için fark ihmal edilebilir düzeydedir.

MutableState, Composable işlev argümanı olarak kullanılabilir mi?

Mümkündür ancak önerilmez. MutableState yerine, State (salt okunur) + bir onValueChange lambda'sı geçirin. Bu, State Hoisting kalıbını uygular ve bileşeni yeniden kullanılabilir hale getirir. MutableState kabul eden bileşenler, tek yönlü veri akışını ihlal eder.

Özel bir MutableState uygulaması nasıl oluşturulur?

MutableState arayüzünü uygulayın ve bir getter ve setter ile override var value sağlayın. Setter'da doğrulama veya günlükleme ekleyebilirsiniz. Compose Runtime ile geriye dönük uyumluluk için, özel uygulamanızı snapshotFlow içine sarın veya snapshotIncrement kullanın.

Özet

  • MutableState — Compose'da değiştirilebilir gözlemlenebilir durum için temel arayüz
  • State — değiştirme hakkı olmadan veri iletmek için salt okunur sürüm
  • SnapshotMutationPolicy değişiklikte yeniden oluşturma tetikleme koşullarını yönetir
  • İlkel State (MutableIntState ve diğerleri) boxing yükünü ortadan kaldırır
  • SnapshotStateList ve SnapshotStateMap koleksiyon içi değişiklikleri izler
  • Yeniden oluşturma, value setter'ının herhangi bir çağrısında otomatik olarak tetiklenir
  • Öneri: duruma sahip olmak için MutableState, aşağı iletmek için State kullanın

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.

Projeyi tartış

Ayrıca okuyun