我们一般会监听文本变化,文本变化后就发起搜索请求。
但现在有两个问题
1. 毫无意义的中间搜索
比如用户快速输入123456789,我们希望只发起一次请求123456789,而不是发起9次请求(每次变化都发起请求),我们可以使用sample操作符
2.请求和响应顺序不一致导致显示的结果有误
比如我们先搜索123再搜索456,按照正常顺序123的搜索结果先返回,456的搜索结果后返回,页面最终显示456的搜索结果,没毛病。
但如果先返回456的搜索结果,再返回123的搜索结果,就会出现123的搜索结果覆盖456的搜索结果,结果就是错的。解决方法是mapLatest操作符。
代码如下
class MainActivity : AppCompatActivity() {
private val _search = MutableStateFlow("")
private lateinit var content: TextView
private lateinit var editText: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content)
editText = findViewById(R.id.search)
lifecycleScope.launch {
_search.sample(500)
.filter {
it.isNotEmpty()
}
.mapLatest {
map(value = it)
}.collect {
Log.d("TAG", "收到了结果 $it")
content.text = it
}
}
editText.addTextChangedListener {
_search.value = it.toString()
}
}
private var current = 5
private suspend fun map(value: String): String = withContext(Dispatchers.IO) {
Log.d("TAG", "发起了请求 $value ,delay = $current")
delay(current * 1000L)
current -= 3
if (current <= 0) {
current = 5
}
value
}
}
网友评论