Skip to content

Instantly share code, notes, and snippets.

@DevPicon
Created January 9, 2021 19:36
Show Gist options
  • Save DevPicon/e6af289bd9f4131ac971ff78cf6bf3e4 to your computer and use it in GitHub Desktop.
Save DevPicon/e6af289bd9f4131ac971ff78cf6bf3e4 to your computer and use it in GitHub Desktop.
StateFlow and Sharedflow... the end of LiveData?
package sharedflow.macao.flow
import flow.others.log
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.random.Random
fun main() {
runBlocking {
delay(1000)
emitRandomNumbers()
.filter { value -> value % 2 == 0 }
.collect { value ->
log("Collector A: collected value $value")
}
}
}
fun emitRandomNumbers() = flow<Int> {
for (value in 0..100) {
delay(500)
log("Emitted value: $value")
emit(value)
}
}
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import pe.devpicon.android.compose.chukyeats.repository.FoodRepository
class FoodDetailViewModel : ViewModel() {
private val _detail: MutableLiveData<ScreenState> = MutableLiveData(ScreenState.Loading)
val detail: LiveData<ScreenState> = _detail
fun load(id: String) {
viewModelScope.launch {
try {
_detail.postValue(
ScreenState.Ready(FoodRepository.getFoodDetail(id))
)
} catch (e: Exception) {
_detail.postValue(ScreenState.Error(e.message ?: "This an unhandled error"))
}
}
//...
}
}
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import pe.devpicon.android.compose.chukyeats.repository.FoodRepository
class FoodDetailViewModelStateFlow : ViewModel() {
private val _detailB: MutableStateFlow<ScreenState> = MutableStateFlow(ScreenState.Loading)
val detailB: StateFlow<ScreenState> = _detailB
fun load(id: String) {
viewModelScope.launch {
try {
_detailB.value = ScreenState.Ready(FoodRepository.getFoodDetail(id))
} catch (e: Exception) {
_detailB.value = ScreenState.Error(e.message ?: "This an unhandled error")
}
}
//...
}
}
package sharedflow.macao
import flow.others.log
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.random.Random
fun main() {
val broadcastChannel = MyBroadcastChannel()
runBlocking {
launch {
emitterRandomIntegers().collect { value ->
broadcastChannel.postNewInteger(value)
}
}
launch {
delay(3000)
broadcastChannel.integers.collect { collectedValue ->
log("Collector A collected $collectedValue")
}
}
launch {
delay(5000)
broadcastChannel.integers.collect { collectedValue ->
log("Collector B collected $collectedValue")
}
}
}
}
class MyBroadcastChannel {
private val _integers = MutableSharedFlow<Int>(
extraBufferCapacity = 3,
onBufferOverflow = BufferOverflow.DROP_LATEST,
replay = 3
)
val integers = _integers.asSharedFlow()
suspend fun postNewInteger(newValue: Int) {
_integers.emit(newValue)
}
}
fun emitterRandomIntegers() = flow<Int> {
while (true) {
delay(1000)
val random = Random.nextInt(0, 200)
log("Emitter - emitted value $random")
emit(random)
}
}
package sharedflow.macao
import flow.others.log
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class StateModel {
private val _state = MutableStateFlow(0)
val state = _state.asStateFlow() // read-only public view
fun update(newValue: Int) {
_state.value = newValue // NOT suspending
}
}
fun main() {
val stateModel = StateModel()
runBlocking {
launch {
flow<Int> {
for (x in 1..6) {
log("emitting value $x")
emit(x)
}
}.collect { emmitedValue -> stateModel.update(emmitedValue) }
}
launch {
delay(2000)
stateModel.state.collect { value -> log("observed? value. $value") }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment