Akışlara giriş

Home API'lerin Kotlin sürümü, Kotlin dilinin bir özelliği olan akışları kullanır. Bu özellik, dönüştürme, filtreleme, eşleme, koleksiyonlara dönüştürme ve koleksiyonlardan dönüştürme vb. dahil olmak üzere asenkron veri akışlarını işlemek için güçlü özellikler sunar.

Komut dizileri, akışlarla yakından ilişkilidir ve asenkron kod yazmak için zarif bir soyutlama sağlar. Ayrıca geliştiriciyi, geri çağırma rutinlerini açıkça yazma zorunluluğundan kurtarır. Akışlar, bir işlevin veya iş parçacığının tamamlanmasını beklemek zorunda kalmadan, coroutine'lerden verileri asynkron olarak almak için coroutine'lerle birlikte çalışır.

Veriler, toplama adı verilen bir süreçte tüketici tarafından bir akıştan alınır. Kotlin akışlarında bu amaç için kullanılabilecek bir collect() işlevi vardır. Toplama sırasında bir akışta ne olacağı, akışın türüne bağlıdır.

Kotlin akışları (Flow<T>) varsayılan olarak soğuktürdedir. Yani akış oluşturucu kodu yalnızca collect() çağrıldığında veri üretir. Buna karşılık sıcak akış, verileri hemen üretir ve veriler tüketildiğinde bir sıra gibi bellekte arabelleğe alır. Verileri bellekte sakladığından, sıcak akışların durum bilgisine sahip olduğu kabul edilir.

Akışlar, shareIn operatörü kullanılarak soğuktan sıcak akışa dönüştürülebilir (shareIn kullanarak soğuk akışları sıcak akışa dönüştürme başlıklı makaleyi inceleyin). Soğuk bir akışı sıcak akışa dönüştürmek için SharedFlow veya StateFlow operatörlerini de kullanabilirsiniz.

Örnek uygulamada akışlar nasıl kullanılır?

Örnek uygulama, Home API'lerindeki akışlara bağlı Jetpack Compose'daki görüntüleme modellerini kullanır. Örnek uygulama kullanıcı arayüzü öğelerinin çoğu duruma göre yönlendirilir ancak bunlarla etkileşim kurulabilir. Örnek uygulama, gerçek zamanlı kullanıcı deneyimi için cihazlardaki durumu kullanıcı arayüzündeki "iyimser" durumla da birleştirir. İyimserlik terimi, uygulamanın belirli bir işlemin başarılı olduğunu varsaydığı ve onay beklemeden kullanıcı arayüzünü beklenen sonucu yansıtacak şekilde hemen güncellediği anlamına gelir. İşlemin başarısız olduğu anlaşılırsa kullanıcı arayüzü gerçek durumu yansıtacak şekilde güncellenir.

Örnek uygulamada, görünüm modelinin her katmanı (yapılar, odalar, cihazlar) için akışlar oluşturulur. Örneğin, GlobalViewModel.kt'te aşağıdaki çağrıya sahip yapılar için bunu yapar:

  fun getStructuresState(): StateFlow<List<StructureModel>?> =
    homeClient
      .structures()
      .map { structures -> structures.map { StructureModel(it.name, it) }.sortedBy { it.name } }
      .handleErrors()
      .flowOn(Dispatchers.IO)
      .stateIn(scope = viewModelScope, started = SharingStarted.WhileSubscribed(), null)

emitAll(), belirli bir akıştaki tüm değerleri toplar ve toplayıcıya gönderir. stateIn(), yayın akışının tek bir çalışan örneğinden en son yayınlanan değeri birden fazla yayın abonesiyle paylaşır. Daha fazla bilgi için kotlinx.coroutines.flow referansını inceleyin.

Jetpack Compose

Akış nesnelerini yerel bellekte depolamak ve sonlandırılmalarını önlemek için Kotlin remember API'sini kullanın.

Jetpack Compose'da bunu collectAsStateWithLifecycle() ile kullanırsanız Jetpack, bu durumu gösteren uygulama kullanıcı arayüzünün gerçekten ön planda olup olmadığına bağlı olarak akışlara abone olma ve abonelikten çıkma işlemlerini otomatik olarak yönetir.

Örnek uygulamada basit bir çağrı bunu yapar. Daha önce gösterilen getStructuresState() işlevini kullanarak:

val structuresList by
    remember(globalViewModel) { globalViewModel.getStructuresState() }.collectAsStateWithLifecycle()

Artık yapının herhangi bir durumu değiştiğinde (name gibi), bu durumu kullanan Composable işlevi bu güncellenmiş durumu otomatik olarak yansıtır. Örnek uygulamada bu, HomeActivityContent() işlevidir.

Kaynaklar

Kotlin, akışlar, iş parçacığı ve Jetpack Compose hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın: