一、一句话理解 filter
filter的作用是:只让"符合条件"的数据通过,不符合的直接丢掉。
你可以把它想象成一个"筛子":
- 数据流进来
filter按你定的规则检查每个值- 只有满足条件的才能流出去,其他的被过滤掉
二、基本语法
flow.filter { value ->
// 返回 true:保留这个值
// 返回 false:丢弃这个值
}
三、简单例子 🌰
假设你有一个发出数字的 Flow:
val numbers = flowOf(1, 2, 3, 4, 5, 6)
你只想处理偶数:
val evenNumbers = numbers.filter { it % 2 == 0 }
// 结果 Flow 会发出:2, 4, 6
四、Android 实战场景 📱
场景1:只显示"已激活"的用户
假设你从数据库获取用户列表:
data class User(val id: Int, val name: String, val isActive: Boolean)
// Repository 返回 Flow<List<User>>
val allUsers: Flow<List<User>> = userRepository.getAllUsers()
但 UI 只想显示 isActive == true 的用户。
✅ 用 filter(注意:这里是对列表中的每个用户过滤):
val activeUsers: Flow<List<User>> = allUsers.map { users ->
users.filter { user -> user.isActive } // 这是 List 的 filter
}
🔍 注意:这里用的是 List 的
filter,因为 Flow 发出的是整个列表。如果 Flow 是逐个发出 User(比如
Flow<User>),那就直接用 Flow 的filter:
val activeUserStream: Flow<User> = userEventStream.filter { it.isActive }
场景2:搜索框防抖后过滤空输入
用户在搜索框输入,你用 callbackFlow 或 StateFlow 监听输入:
val searchQueries: StateFlow<String> = mutableSearchQuery.asStateFlow()
你不希望在用户输入空字符串或长度太短时发起网络请求:
lifecycleScope.launch {
searchQueries
.map { it.trim() } // 先 trim
.filter { it.length >= 2 } // 只有 >=2 个字符才继续
.debounce(300) // 防抖
.collect { query ->
searchRepository.search(query) // 安全发起请求
}
}
✅ 这样就避免了无效请求(比如搜一个字母或空格)。
五、filter 的关键特点
| 特点 | 说明 |
|---|---|
| ✅ 同步判断 | lambda 里不能直接调用 suspend 函数(和 map 一样) |
| 🔽 可能"卡住" | 如果所有数据都不符合条件,下游就收不到任何值(这是正常行为!) |
| 🔄 不改变数据类型 | 输入是 Flow<T>,输出还是 Flow<T>,只是元素变少了 |
六、常见误区
❌ 误区1:在 filter 里做网络请求或数据库查询
someFlow.filter { value ->
someSuspendFunction(value) // ❌ 编译错误!不能挂起
}
✅ 正确做法:如果需要异步判断,考虑用 transform 或提前在 Repository 层处理。
❌ 误区2:以为 filter 会"跳过" collect
flow.filter { it > 5 }.collect { println(it) }
// 如果所有值 ≤5,collect 里的代码根本不会执行 ------ 这是正确的!
这其实是 filter 的正常行为:没有符合条件的数据,就不发射。
七、和其他操作符搭配使用(超常用!)
Flow 的强大在于链式调用,比如:
flowOf("apple", "banana", "cherry", "date")
.filter { it.length > 5 } // 只保留长度 >5 的
.map { it.uppercase() } // 转大写
.collect { println(it) } // 输出:BANANA, CHERRY
在 Android 中,你经常会看到这样的链:
searchQuery
.map { it.trim() }
.filter { it.isNotEmpty() }
.debounce(400)
.distinctUntilChanged()
.map { performSearch(it) }
.catch { showError(it) }
.collect { updateUI(it) }
八、总结一句话
filter是 Flow 中用来"筛选数据"的操作符,只让满足条件的元素继续流动,非常适合在 Android 开发中做输入验证、状态过滤、避免无效操作等场景。
它和 map 一样,是 Flow 最基础、最常用的"组合积木"之一。