我有一个场景,我有一个函数 scanForTargets,它返回一个 FoundNumber 类型的 Observable。在 FoundNumber 中,我只需要一个可以从中获取的 ID 字段。当每个元素都返回到 scanResults Observable 中时,我想检查名称字段是否与目标列表中的一个名称匹配。如果是这样,那么我想发出它。例如,如果我要查找数字 1 和 2,并且 scanForTargets() 会返回 1、2、3 和 4,那么我希望 scanForValues 仅返回 1 和 2。
需要注意的是,我只想继续这样做,直到:1)经过一段时间(在这种情况下我抛出并出错)2)在超时之前找到字符串列表中的所有项目。
我到目前为止看起来像这样,但我无法让它为我工作,主要是因为停止一次的捷径/如果在超时之前找到所有目标。
fun scanForValues(targetList: List<String>): Observable<FoundNumber> {
val scanResult = scanForTargets()
return scanResult.doOnNext {scanResult -> Log.d(TAG, "Found potential target: " + scanResult.name) }
.filter(TargetPredicate(targetList)) //See if it's one of those we want
.timeout(5, TimeUnit.SECONDS) //Wait a max of 5 seconds to find all items
.doOnError { Log.w(TAG, "Failed to scan"}") }
.map{s->scanResult.name}
}
class TargetPredicate(private val targetList: List<String>) : Predicate<ScanResult> { override fun test(scanResult: ScanResult): Boolean {
if(scanResult == null) {
return false
}
return scanResult.name in targetList
}
}
如果我找到列表中的所有项目,如何添加检查以停止?我不能只添加另一个谓词,对吗?
谢谢。
更新:根据要求,这里有一些数据来说明我的意思。
假设 scanForTargets() 和支持代码如下所示:
var emittedList: List<String?> = listOf(null, "0", "1", "2", "3")
fun scanForTargets(): Observable<FoundNumber> = Observable
.intervalRange(0, emittedList.size.toLong(), 0, 1, TimeUnit.SECONDS)
.map { index -> FoundNumber(emittedList[index.toInt()]) }
data class FoundNumber(val targetId: String?)
现在,如果使用 1 和 2 的列表调用 scanForValues,那么它应该返回一个 1 和 2 的 Observable。