StateFlow
ve SharedFlow
Akış API'leridir
akışların en uygun şekilde durum güncellemelerini ve birden çok kullanıcıya değer yayan
yardımcı olur.
StateFlow
StateFlow
geçerli ve yeni durum yayan, durum sahibi gözlemlenebilir bir akıştır
güncellemelerine göz atacağız. Geçerli durum değeri,
value
Durumu güncellemek ve akışa göndermek için şuna yeni bir değer atayın:
öğesinin value
özelliği
MutableStateFlow
sınıfı.
Android'de StateFlow
, bakımını yapması gereken sınıflar için
bir değişiklik gösterebilir.
Kotlin akışlarına ilişkin örneklerde, bir StateFlow
View
'ın bunu yapabilmesi için,LatestNewsViewModel
kullanıcı arayüzü durumu güncellemelerini dinleme ve doğası gereği ekran durumunun
yapılandırma değişiklikleridir.
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
// Backing property to avoid state updates from other classes
private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
// The UI collects from this StateFlow to get its state updates
val uiState: StateFlow<LatestNewsUiState> = _uiState
init {
viewModelScope.launch {
newsRepository.favoriteLatestNews
// Update View with the latest favorite news
// Writes to the value property of MutableStateFlow,
// adding a new element to the flow and updating all
// of its collectors
.collect { favoriteNews ->
_uiState.value = LatestNewsUiState.Success(favoriteNews)
}
}
}
}
// Represents different states for the LatestNews screen
sealed class LatestNewsUiState {
data class Success(val news: List<ArticleHeadline>): LatestNewsUiState()
data class Error(val exception: Throwable): LatestNewsUiState()
}
MutableStateFlow
öğesinin güncellenmesinden sorumlu sınıf yapımcıdır,
ve StateFlow
verisinden toplanan tüm sınıflar tüketicidir. Beğenmeyi kaldır
flow
oluşturucu kullanılarak oluşturulan soğuk akış, StateFlow
sıcaktır:
bir üretici kodunu tetiklemez. StateFlow
her zaman etkin ve bellektedir ve çöpe atılmaya uygun hale gelir.
yalnızca bir çöpten başka bir referans olmadığında koleksiyonu
koleksiyon kökü.
Yeni bir tüketici akıştan veri toplamaya başladığında, ilk olarak
durumundaki durumu ve sonraki durumları gösterir. Bu davranışı,
diğer gözlemlenebilir sınıflarda
LiveData
.
View
, diğer akışlarda olduğu gibi StateFlow
öğesini dinler:
class LatestNewsActivity : AppCompatActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
...
// Start a coroutine in the lifecycle scope
lifecycleScope.launch {
// repeatOnLifecycle launches the block in a new coroutine every time the
// lifecycle is in the STARTED state (or above) and cancels it when it's STOPPED.
repeatOnLifecycle(Lifecycle.State.STARTED) {
// Trigger the flow and start listening for values.
// Note that this happens when lifecycle is STARTED and stops
// collecting when the lifecycle is STOPPED
latestNewsViewModel.uiState.collect { uiState ->
// New value received
when (uiState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
}
}
}
}
Herhangi bir akışı StateFlow
biçimine dönüştürmek için
stateIn
ara operatör.
StateFlow, Flow ve LiveData
StateFlow
ve LiveData
irdeleyelim. Her ikisi de gözlemlenebilir veri sahibi sınıflarıdır ve her ikisi de
benzer bir kalıpla karşılaşabilirsiniz.
Ancak StateFlow
ve
LiveData
farklı davranır:
StateFlow
, oluşturucuya bir başlangıç durumunun iletilmesini gerektirir. ancakLiveData
bunu yapmaz.LiveData.observe()
, görünümüSTOPPED
durumuna geçerkenStateFlow
veya diğer akışlar otomatik olarak toplanmaya son vermez. Aynı hedefe ulaşmak için akışını birLifecycle.repeatOnLifecycle
verisinden toplamanız gerekir. engelleyebilirsiniz.
Soğuk akışları shareIn
kullanarak ısıtma
StateFlow
, sıcak bir akıştır. Akış olduğu sürece bellekte kalır
veya bu verilere ilişkin diğer referanslar bir atık koleksiyonunda bulunuyorsa
kök. Soğuk akışları sıcak duruma getirmek için
shareIn
operatörümüzü kullanabilirsiniz.
Kotlin akışlarında oluşturulan callbackFlow
öğesini bir
her koleksiyoncunun yeni bir akış oluşturmasını istemek yerine,
shareIn
kullanılarak toplayıcılar arasında Firestore'dan alınan veriler.
Şu belgeleri geçmeniz gerekir:
- Akışı paylaşmak için kullanılan bir
CoroutineScope
. Bu kapsam, şu anki ihtiyaç kadar uzun tutmaktır. - Her yeni koleksiyoncu için tekrar oynatılacak öğe sayısı.
- Başlangıç davranışı politikası.
class NewsRemoteDataSource(...,
private val externalScope: CoroutineScope,
) {
val latestNews: Flow<List<ArticleHeadline>> = flow {
...
}.shareIn(
externalScope,
replay = 1,
started = SharingStarted.WhileSubscribed()
)
}
Bu örnekte, latestNews
akışı yayınlanan son öğeyi tekrar oynatır
yeni bir toplayıcıya gönderir ve externalScope
olduğu sürece etkin kalır.
hâlâ canlı olduğunu ve etkin koleksiyoncuların bulunduğunu gösteriyor. SharingStarted.WhileSubscribed()
başlatma politikası etkin olduğunda yukarı akış üreticisini etkin tutar
abone. Şu gibi başka başlangıç politikaları da kullanılabilir:
SharingStarted.Eagerly
yazarak yapımcıyı hemen başlatabilirsiniz.
İlk abone gösterildikten sonra paylaşmaya başlamak için SharingStarted.Lazily
ve akışın sonsuza kadar etkin olmasını sağlayın.
SharedFlow
shareIn
işlevi, değerler yayan bir sıcak akış olan SharedFlow
döndürür.
tüm tüketicilerin kullanımına sunuyor. SharedFlow
,
StateFlow
öğesinin yüksek düzeyde yapılandırılabilir genelleştirilmesi.
shareIn
kullanmadan bir SharedFlow
oluşturabilirsiniz. Örneğin,
uygulamanın geri kalanına işaret göndermek için bir SharedFlow
kullanabilir
tüm içerik düzenli aralıklarla aynı anda yenilenir. Şu bölgelerden:
en son haberleri almak için,
kullanıcıyı bilgilendirmek,
bilgi bölümünde bulabilirsiniz. Sonraki
kod snippet'i kullanıyorsanız TickHandler
bir SharedFlow
gösterir. Böylece diğer
içeriğini ne zaman yenilemesi gerektiğini bilir. StateFlow
konusunda olduğu gibi,
bir sınıfta öğe göndermek için MutableSharedFlow
türündeki yedekleme özelliği
akışla aynıdır:
// Class that centralizes when the content of the app needs to be refreshed
class TickHandler(
private val externalScope: CoroutineScope,
private val tickIntervalMs: Long = 5000
) {
// Backing property to avoid flow emissions from other classes
private val _tickFlow = MutableSharedFlow<Unit>(replay = 0)
val tickFlow: SharedFlow<Event<String>> = _tickFlow
init {
externalScope.launch {
while(true) {
_tickFlow.emit(Unit)
delay(tickIntervalMs)
}
}
}
}
class NewsRepository(
...,
private val tickHandler: TickHandler,
private val externalScope: CoroutineScope
) {
init {
externalScope.launch {
// Listen for tick updates
tickHandler.tickFlow.collect {
refreshLatestNews()
}
}
}
suspend fun refreshLatestNews() { ... }
...
}
SharedFlow
davranışını aşağıdaki şekillerde özelleştirebilirsiniz:
replay
, yeni reklam öğesi için önceden yayınlanmış birkaç değeri yeniden göndermenize abone.onBufferOverflow
, tampon ya da esneme payının ne zaman gönderilecek öğe dolu. Varsayılan değerBufferOverflow.SUSPEND
ise bu da arayanı askıya alır. Diğer seçenekler:DROP_LATEST
veyaDROP_OLDEST
.
MutableSharedFlow
, şunu da içeren bir subscriptionCount
özelliğine sahip:
İşletmenizi optimize edebilmek için etkin toplayıcıların sayısını
ve mantığı buna göre şekillendirebilir. MutableSharedFlow
, bir resetReplayCache
içeriyor
işlevini kullanabilirsiniz.
Ek akış kaynakları
- Android'de Kotlin akışları
- Android'de Kotlin akışlarını test etme
- flow'un ShareIn ve stateIn operatörleri hakkında bilinmesi gerekenler
- LiveData'dan Kotlin Akışı'na Geçiş
- Kotlin eş yordamları ve akışı için ek kaynaklar