我正在扫描一个列表,并在mutableList中添加一个唯一的项目。扫描一个项目通过ScanCallback,但下面的例子是使用Kotlin流更好地理解和做一个简单的用例。我正在给出一个发射不同类型项目的例子。
基本上我想从特定条件中删除项:-
-
当流量数据完成时发出新的值。
-
当发送一个物品时,如果我们在30秒内不再收到一个物品,那么我们将该物品从列表中删除。
import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.runBlocking class ItemList { val scanResultList = mutableListOf<ScanResults>() fun doSomething(): Flow<ScanResults> = flow { (0..20).forEach { delay(200L) when (it) { in 10..12 -> { emit(ScanResults(Device("item is Adding in range of 10 -- 20"))) } in 15..18 -> { emit(ScanResults(Device("item is Adding in range of 15 -- 18"))) } else -> { emit(ScanResults(Device("item is Adding without range"))) } } } } fun main() = runBlocking { doSomething().collectLatest { value -> handleScanResult(value) } } private fun handleScanResult(result: ScanResults) { if (!scanResultList.contains(result)) { result.device?.name?.let { if (hasNoDuplicateScanResult(scanResultList, result)) { scanResultList.add(result) println("Item added") } } } } private fun hasNoDuplicateScanResult(value: List<ScanResults>, result: ScanResults): Boolean { return value.count { it.device == result.device } < 1 } data class ScanResults(val device: Device? = null) data class Device(val name: String? = null) }
我没有添加Set
,因为在SnapshotStateList中不可用于jetpack撰写。
我试着用简单的术语来解释这个问题。我说输入是一个假想的数据类DeviceInfo
的流,这样更容易描述。
问题:有一个DeviceInfo
s源流。我们希望我们的输出是Set<DeviceInfo>
的流,其中Set是过去30秒内从源发出的所有DeviceInfo。
(如果您愿意,您可以将此输出流转换为状态,或者收集它并使用它更新mutablestateListOf
,等等)
用唯一ID标记每个传入的DeviceInfo(可以基于系统时间或UUID)。用最新的ID将每个DeviceInfo添加到Map中。启动延迟30秒的子协同程序,如果ID匹配,则从映射中删除项目。如果新值已经到达,那么ID将不匹配,因此过时的子协程将静默地过期。
val sourceFlow: Flow<DeviceInfo> = TODO()
val outputFlow: Flow<Set<DeviceInfo>> = flow {
coroutineScope {
val tagsByDeviceInfo = mutableMapOf<DeviceInfo, Long>()
suspend fun emitLatest() = emit(tagsByDeviceInfo.keys.toSet())
sourceFlow.collect { deviceInfo ->
val id = System.currentTimeMillis()
if (tagsByDeviceInfo.put(deviceInfo, id) == null) {
emitLatest() // emit if the key was new to the map
}
launch {
delay(30.seconds)
if (tagsByDeviceInfo[deviceInfo] == id) {
tagsByDeviceInfo.remove(deviceInfo)
emitLatest()
}
}
}
}
}