Flow.shareIn 与 Flow.stateIn 操作符能够将冷流转换为暖流: 它们能够将来自上游冷数据流的信息广播给多个收集者。这两个操作符一般用于提接口crc过错计数高功用: 在没有收集者时参与缓冲Google;或许爽性作为一种缓存机制运用。
留心 : 冷流 是按需创立接口和抽象类的差异的,而且会在它们被查询时发送数据;暖接口和抽象类的差异流 则总是生动,不管是否被源码年代训练怎么样查询,它们都能发工商银行送数据。
本文将会经过示例帮源码网站您了解 shareIn 与 stateIn 操作符。您将学到宫颈癌前期症状怎样针对特定用例配备它们,并防止或许遇到的常见骗局。
底层数据流生产者
持续运用我 之前文章 中运用过的比如——运用底层数据流生产者宣告方位更新。它是一个运用 callbackFlow 结束的 冷流。每个新的收集者都会触发数据流的生产者代码块,一起也会将新的回调参与到 FusedLocationProviderClient。
c函数调用的三种方法lass LocationDataSource(
private val l函数调用语句funcocationClient: FusedLo枸杞cationProviderClient
) {
val locatio源码编辑器ns函数调用进程Source: Flow<Location> = calgoogle服务框架lbackFlow<Location> {
val callback = object : LocationCallback() {
overrid源码年代训练怎么样e fun onLocationResult(result: LocationResult?) {
r源码资源站esult ?: return
try { offer(result.lastLocation) } catch(e: Exception) {}
}
}
requestLocationUpdates(createLocationRequest(), callback, Looper.g接口etMainLooper())
.addOnFailureListener { e ->
close(e) // in case of exception, close the Flow
}
// 在 Flow 结束收集时进行整理
awaitClose {
removeLocati源码精灵onUpdates(call函数调用back)
}
}
}
让咱们看看在不同的接口卡用例下怎样运用 shareIn 与 st源码买卖网站源码ateIn 优化 locat源码年代训练怎么样ion函数调用进程sSource 数据流。
sh源码网站areIn 仍是 stateIn?
咱们要评论接口类型的第一个论题是 shareIn
与 stateIn
之间龚俊的差异。shareIn
操作符回来的是 SharedFlow 而 stateI工商银行客服电话n
回来的是 StateFlow。
留心 : 要了解有关
StgoogleplayateFlow
与SharedFl宫颈癌ow
的更多信息,能够检查 咱们的文档 。函数调用中的参数太少
StateFlow 是 SharedFlow 的一种特别配备,旨在优化同享状况: 毕竟被发送的项目会从头发送给新的收集者,而且这些项目会运用 Any.equals 进行合并。您接口类型能够在 StateFlow 文档 中检查更多相关信息。
两者google服务框架之间的最主要差异,在于 StateFlow
接口容许您经过读取 value
特源码买卖网站源码色同步拜访其毕竟宣告的值。而这不是 SharedFlow
的运用方法。
进步功用
经过同享悉数收集者要查询的同一数据流实例 (而不是按需创立同一个数据流的新实例),这些 API 能够为咱们接口自动化进步功用。
不才面的比如中,LocationRepository
消费了 LocationDataSource
显源码编辑器露的 locationsSource
数据流,一起运用了 shareIn 操作符,然后让每个对用户方位信息感兴趣的收集者都从同一数据流实例中收集数据。这儿只创立了一个 locationsSource
数据流实例并googleplay下载由悉数收集者同享:
class Locati函数调用进程onR枸杞epository(
private val locati函数调用中的参数太少onDataSour公积金ce: LocationDataSource,
private val extern函数调用alScope: CoroutineScogoogle商店pe
) {
val locations: Flow&函数调用的三种方法lt;Location> =公积金
locationDataSource.locat接口自动化ionsSource.shareIn(externalScope, WhileSubscribed())
}
WhileSubscribed 同享战略用工商银行客服电话于在没有收集者时吊销上游数据流。这样一来,咱们便能在接口和抽象类的差异没有程序对方位更新感兴趣时防止资源的浪费。
Android 运用小提示! 在大部分状况下,您能够运用 WhileS狗狗币ubscribed(5000),当毕竟一个函数调用时的实参和形参之间传递收集者消失后再坚持上游数据流生动状况 5 秒钟。源码资源站这样在某些特定状况 (如配备改动) 下能够防止重启上游数据流。当上游数据流的创立本钱很高,或许在 ViewModel 中运用这些操作符时,这一技巧特别有用。
缓冲作业
不才面的比如中,咱们狗狗币的需求有所改动。现在要求咱们坚持监听方位更新,一起要在运用从后台回来前台时在屏幕上显现毕竟的 10 个方位:
class LocationRepository(
private val locationDataSoGource: LocationDataSource,
private val externalScope: CoroutineScope
) {
val locatio源码买卖网站源码ns: Flow<函数调用时的实参和形参之间传递Location> =
locationDataSource.locationsSource
.shareIn(externalSc函数调用语句ope, SharingStarted.Eage源码本钱rly, replay = 10)
}
咱们将参数 replay
的值设置为 10,来让毕竟宣告的 10 个项目坚持在内存中,一起在每次有收集者查询数据流时从头发送这些项目。为了坚持内部数据流一向处于生动状况并发送方位更新,咱们运用了工商银行客服电话同享战略 SharingStarted.Eagerly
,这样就算没有收集者,也宫颈癌前期症状能一向监听更新。
缓存源码精灵数据
咱们的需求再次发生变化,这次咱们不再需求运用处于后台时 持续 监听方位更新。不过公积金,咱们需求缓存毕竟发送的项目,让用户在获取其时方位时能在屏幕上看到一些数据 (即便数据是旧的)。源码本钱针对这种状况,咱们能够运用 stateIn 操作符。
class LocationRep函数调用语句ository(
private val locationDataSource: Location函数调用不能够DataSource,
private val externalScope: CoroutineScope
) {
val location源码本钱s: Flow<Loca龚俊tion> =
locationDataSource.locationsSource.stateIn(externa接口类型lScope, WhileSubscribed(), EmptyLocation)
}
Flow.stateIn
能够缓存毕竟发送的项目,偏重放给新的收集者接口无权限。
留心!不要在每个函数调用时创立新的实例
切勿 在调用某个函数调用回来时,运用 shareIn 或 stateIn接口crc过错计数 创立新的数据流。这样会在每次函数调用时创立一个新的函数调用的三种方法 Share接口测试面试题dFlow 或 StateFlow,而它们将会一向坚持在内存中,枸杞直到作用域被吊销或许在没有任何引用时被废物回收。
class U枸杞serRepository(
private val usegoogle地球rLocalDagoogle谷歌查找主页taSource: UserLocalDataSource,
private val externalSco源码年代pe: CoroutineScope
) {
// 不要像这样在函数中运用 shareIn 或 stateI狗狗币n
// 这将在每次调用时创接口卡建新的 SharedFlow 或 StateFlow,接口测试面试题而它们将不会被复用。
fun getUser(): Flow源码精灵&l函数调用能够作为一个函数的形参t;User> =
userLocalDataSource.getUser()
.shareIn(google空间externa接口无权限是什么意思lScope, WhileSgoogle翻译ubscribed())
// 能够在特色中运用 shareIn 或 stateIn
val user: Flow<User> =
userLocalDataSource.getUsergoogle谷歌查找主页().shareIn(extegooglernalScope, WhileSubscribed(源码之家))
}
需求入参的数据流
需求入参 (如 userId
) 的数据流无法简略地运用 shareIn
或 stateIn
同享。以开源项目——G接口卡oogle I/O 的 Android 运用 iosched 为例,您能够在 源码中 看到,从 Firestore 获取用户作业的数据googleplay流是经过 callbackFlow
结束的。由于其接纳 userId
作为参数,因此无法简略运用 shareIn
或 stateIn
操源码买卖网站源码作符对其进行复用。
class UserRepository(
private val userEventsDataSource: FirestoreUserEventDataSource
) {
// 新的收集者会在 Fire函数调用栈store 中注册为新的回调。
// 由于这一函数依靠一个 `userId`,所以在这个函数中
// 数据流无法经过调用 shareIn 或 stateIn 进行复用.
// 这样会导致每次调用函数时,都会创立新的 Shared工商银行客服电话Flow 或 StateFlow
fun getUserEvents(userId: String): Flow<UserEventsResult> =
userLocalDataSource.getObservableUserEvents(userId)
}
怎样优化这一用例取决于您运用的需求:
- 您是否容许一起函数调用能够作为一个函数的形参从多个用户接纳作业?假设答案是肯定的,您或许需求为
SharedFlow工商银行客服电话
或StateFlow
实例创立一个 map,并在subscripti接口crc过错计数onCount
为 0 时移除引用并退出上游数据流。 - 假设您只容许一个用户,而且收集者需求更新函数调用的三种方法为查询新的用户,您能够向一个悉数收集者共用的
SharedFlow
或StateFlow
发送作业更新,并将公共数据流作为类中的变量。
sha函数调用的三种方法reIn
与 stateIn
操作符能够与冷流一起运用来进步功用,您能够运用它们在没有收集者时增加缓冲,或许直接将其作为缓存机制运用。留心运用它们,不要在每次函数调用时都创立新的数据流实例——这样会导致资源的浪费及意料之外的问题!