https://www.youtube.com/watch?v=M8YtV47kaqA&t=607s
pl学习视频
什么是冷流?
fun fibonacci(): Flow<BigInteger> = flow {
var x = BigInteger.ZERO
var y = BigInteger.ONE
while (true) {
println("fibonacci while $x")
emit(x)
x = y.also {
y += x
}
}
}
这时候试着运行
fun testJob() {
testJob = viewModelScope.launch {
repository.fibonacci()
}
虽然运行了fibonacci(),但是没有任何的打印。原因是,冷流是只有有订阅者后,才开始发送数据。所以需要collect之后,才有数据
fun testJob() {
testJob = viewModelScope.launch {
var i = 0
repository.fibonacci()
.take(100).collect {
i++
println("fibonacci $it")
println("fibonacci $i")
}
}
}
像之前的例子也有说到callbackflow,他也是一个冷流,之前有个例子,监听网络状态
fun networkAvailability(context: Context) = callbackFlow {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
println("network send true")
trySend(true)
}
override fun onLost(network: Network) {
super.onLost(network)
println("network send false")
trySend(false)
}
}
val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
//注册
println("network register")
manager.registerNetworkCallback(
NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build(), callback
)
awaitClose {
//取消注册
println("network unregister")
manager.unregisterNetworkCallback(callback)
}
}
我们监听这个flow
val flow = remember {
viewModel.networkAvailability(applicationContext)
}
val status1 = flow.collectAsStateWithLifecycle(false)
val status2 = flow.collectAsStateWithLifecycle(false)
看下打印情况
可以看到网络监听注册了两次,所以对冷流的数据收集是独立的。这不是我们想要的,我们希望只监听一次,然后只关心最新的数据,这个数据可以多个观察者共享,这时候,就希望把冷流变成热流,shareIn
val rememberCoroutineScope = rememberCoroutineScope()
val flow = remember { viewModel.networkAvailability(applicationContext)
.shareIn(rememberCoroutineScope,
SharingStarted.Eagerly)}
val status1 = flow.collectAsStateWithLifecycle(false)
val status2 = flow.collectAsStateWithLifecycle(false)
只是将flow转换 shareIn之后
只注册了一次
这样就可以避免重复的数据发送
shareIn 和 stateIn区别在于是否缓存最新的值,后续还有区分的视频,如果是事件类型用shareflow像消息提示,snackbar,
如果是UI状态,用stateIn,只关心最新的值