Yaşam döngüsüne duyarlı bileşenlerle Kotlin eş yordamlarını kullanın

Kotlin eş yordamları, asenkron kod yazmanıza olanak tanıyan bir API sunar. Kotlin eş yordamlarıyla, eş yordamlarınızın ne zaman çalışması gerektiğini yönetmenize yardımcı olan bir CoroutineScope tanımlayabilirsiniz. Her eşzamansız işlem, belirli bir kapsamda çalışır.

Yaşam döngüsüne duyarlı bileşenler, uygulamanızdaki mantıksal kapsamlar için eş yordamlara birinci sınıf destek sağlar. Bu belgede, eş yordamların yaşam döngüsüne duyarlı bileşenlerle nasıl etkili bir şekilde kullanılacağı açıklanmaktadır.

Bağımlılık ekleme

Bu konuda açıklanan yerleşik eş yordam kapsamları, Lifecycle API'de yer alır. Bu kapsamları kullanırken uygun bağımlılıkları eklediğinizden emin olun.

  • Compose'daki ViewModel yardımcı programları için implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version") kullanın.
  • Compose'da yaşam döngüsü yardımcı programları için implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version") kullanın.

Yaşam döngüsüne duyarlı eş yordam kapsamları

Compose ve Lifecycle kitaplıkları, uygulamanızda kullanabileceğiniz aşağıdaki yerleşik kapsamları sağlar.

ViewModelScope

Uygulamanızdaki her ViewModel için bir ViewModelScope tanımlanır. ViewModel temizlenirse bu kapsamda başlatılan tüm eş yordamlar otomatik olarak iptal edilir. Yalnızca ViewModel etkin olduğunda yapılması gereken işleriniz varsa eş yordamlar burada faydalı olur. Örneğin, bir düzen için bazı verileri hesaplıyorsanız çalışmayı ViewModel kapsamına almanız gerekir. Böylece, ViewModel temizlenirse kaynak tüketimini önlemek için çalışma otomatik olarak iptal edilir.

Bir ViewModel öğesinin CoroutineScope değerine, ViewModel öğesinin viewModelScope özelliği aracılığıyla erişebilirsiniz. Aşağıdaki örnekte bu durum gösterilmektedir:

class MyViewModel: ViewModel() {
    init {
        viewModelScope.launch {
            // Coroutine that will be canceled when the ViewModel is cleared.
        }
    }
}

Daha ileri düzey kullanım alanları için varsayılan viewModelScope yerine doğrudan ViewModel'in oluşturucusuna özel bir CoroutineScope iletebilirsiniz. Bu yaklaşım, özellikle aşağıdaki durumlarda daha fazla kontrol ve esneklik sağlar:

  • Test: TestScope eklemenize olanak tanır. Bu sayede, zamanı kontrol etmek ve birim testlerinde eş yordam davranışını doğrulamak daha kolay olur.

  • Özel yapılandırma: ViewModel çalışmaya başlamadan önce kapsamı belirli bir CoroutineDispatcher (ör. yoğun hesaplama için Dispatchers.Default) veya özel bir CoroutineExceptionHandler ile yapılandırabilirsiniz.

Oluşturmaya bağlı kapsamlar

Animasyonlar, ağ çağrıları veya zamanlayıcılar gibi yan etkiler, composable'ın yaşam döngüsü kapsamında olmalıdır. Bu sayede, bir composable ekrandan ayrıldığında (oluşturmadan çıktığında) çalışan tüm eş yordamlar otomatik olarak iptal edilir ve bellek sızıntıları önlenir.

Compose, oluşturma kapsamını bildirimli olarak işlemek için LaunchedEffect API'sini sağlar.

LaunchedEffect, askıya alma işlevlerini çalıştırmanıza olanak tanıyan bir CoroutineScope oluşturur. Kapsam, ana makine etkinliğinin yaşam döngüsüne değil, composable'ın oluşturma yaşam döngüsüne bağlıdır.

  • Enter: Oluşturulabilir öğe, oluşturma işlemine girdiğinde eş yordam başlar.
  • Çıkış: Oluşturulabilir öğe, oluşturmadan ayrıldığında eş yordam iptal edilir.
  • Yeniden başlatma: LaunchedEffect öğesine iletilen anahtarlardan herhangi biri değişirse mevcut eş yordam iptal edilir ve yeni bir eş yordam başlatılır.

Aşağıdaki örnekte, yanıp sönen bir animasyon oluşturmak için LaunchedEffect öğesinin nasıl kullanılacağı gösterilmektedir. Eş yordam, bileşenin oluşturmadaki varlığına bağlıdır ve yapılandırma değişikliklerine tepki verir:

// Allow the pulse rate to be configured, so it can be sped up if the user is running
// out of time
var pulseRateMs by remember { mutableLongStateOf(3000L) }
val alpha = remember { Animatable(1f) }
LaunchedEffect(pulseRateMs) { // Restart the effect when the pulse rate changes
    while (isActive) {
        delay(pulseRateMs) // Pulse the alpha every pulseRateMs to alert the user
        alpha.animateTo(0f)
        alpha.animateTo(1f)
    }
}

LaunchedEffect hakkında daha fazla bilgi için Oluşturma'da yan etkiler başlıklı makaleyi inceleyin.

Yaşam döngüsüne duyarlı akış koleksiyonu

Jetpack Compose'da akışları güvenli bir şekilde toplamak için collectAsStateWithLifecycle API'sini kullanın. Bu tek işlev, bir Flow nesnesini Compose State nesnesine dönüştürür ve yaşam döngüsü aboneliğini sizin için otomatik olarak yönetir. Varsayılan olarak, toplama işlemi yaşam döngüsü STARTED olduğunda başlar ve yaşam döngüsü STOPPED olduğunda durur. Bu varsayılan davranışı geçersiz kılmak için minActiveState parametresini istediğiniz yaşam döngüsü yöntemiyle (ör. Lifecycle.State.RESUMED) iletin.

Aşağıdaki örnekte, bir ViewModel'in StateFlow değerinin bir composable'da nasıl toplanacağı gösterilmektedir:

@Composable
private fun ConversationScreen(
    conversationViewModel: ConversationViewModel = viewModel()
) {

    val messages by conversationViewModel.messages.collectAsStateWithLifecycle()

    ConversationScreen(
        messages = messages,
        onSendMessage = { message: Message -> conversationViewModel.sendMessage(message) }
    )
}

@Composable
private fun ConversationScreen(
    messages: List<Message>,
    onSendMessage: (Message) -> Unit
) {

    MessagesList(messages, onSendMessage)
    /* ... */
}

Birden fazla akışın paralel olarak toplanması

Compose'da birden fazla durum değişkeni tanımlayarak birden fazla akışı paralel olarak toplayabilirsiniz. collectAsStateWithLifecycle kendi temel kapsamını yönettiği için paralel toplama otomatik olarak gerçekleştirilir:

@Composable
fun DashboardScreen(viewModel: DashboardViewModel = viewModel()) {
    // Both flows are collected safely in parallel and will emit updates when either changes, the composables will recompose
    val userData by viewModel.userFlow.collectAsStateWithLifecycle()
    val feedData by viewModel.feedFlow.collectAsStateWithLifecycle()

    // ...
}

Flows'u kullanarak değerleri eşzamansız olarak hesaplama

Değerleri eşzamansız olarak hesaplamanız gerektiğinde stateIn operatörüyle StateFlow kullanın.

Aşağıdaki snippet'te, StateFlow değerine dönüştürülmüş standart bir Flow kullanılmaktadır. WhileSubscribed(5000) parametresi, yapılandırma değişikliklerini işlemek için kullanıcı arayüzü kaybolduktan sonra aboneliği beş saniye boyunca etkin tutar.

val uiState: StateFlow<Result> = flow {
    emit(repository.fetchData())
}
.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = Result.Loading
)

Toplanan değerleri Compose State'e dönüştürmek için collectAsStateWithLifecycle kullanın. Böylece kullanıcı arayüzünüz, veriler her değiştiğinde reaktif olarak güncellenebilir.

Durum hakkında daha fazla bilgi için Durum ve Jetpack Compose başlıklı makaleyi inceleyin.

Ek kaynaklar

İçerik görüntüleme

Örnekler