我尝试使用去抖动设置正确的 API 调用。现在我在 ViewModel 中有一个函数,它调用具有延迟(去抖)和唯一(最新)值的 API 搜索请求,但在去抖后,TextField 中的一次更改数量一样多
这是我的代码:
用户界面:
val searchedText by viewModel.searchText.collectAsState()
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(15.dp),
value = searchedText,
onValueChange = { newText ->
viewModel.updateSearchedText(newText)
if (newText.isNotEmpty()) {
viewModel.getSearchedNotifications(5, 0)
} else {
viewModel.getAllNotifications(5, 0)
}
},
视图模型:
private val _searchText = MutableStateFlow("")
val searchText: StateFlow<String> = _searchText
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
fun getSearchedNotifications(
take: Int,
skip: Int
) {
viewModelScope.launch {
_searchText
.debounce(2000L)
.distinctUntilChanged()
.collectLatest { searched ->
val response = notificationsRepository.getNotifications(
take,
skip,
searched
)
when (response) {
is Resource.Success -> {
_notifications.update {
response.data
}
}
is Resource.Error -> {
}
else -> {}
}
}
}
}
例如,我在 TextField 中写入“acc”,延迟 2 秒,之后我有 3 个具有相同参数 acc 的 API 请求。预计用户取消输入后只能有一个带有此参数的请求,并且延迟会超过。
正如 Leviathan 的评论中提到的,TextField 的流问题非常多,因此您应该使用 State 而不是 StateFlow 来保存 TextField 的文本。
每次调用函数时,您都会创建一个新流,这意味着您有多个流更新您的
_notifications
状态或流。
相反,您可以使用函数来更新一个或多个流,这些流馈入您仅创建一次的单个流,并使用
shareIn
或 stateIn
使其持久化。像这样的东西:
var searchText by mutableStateOf("")
private set
private val notificationsTakeAndSkip = MutableSharedFlow<Pair<Int, Int>>(replay = 1)
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
val notifications = snapshotFlow { searchText }
.debounce(2000L)
.distinctUntilChanged()
.combineTransform(notificationsTakeAndSkip.distinctUntilChanged()) { searched, (take, skip) ->
val response = notificationsRepository.getNotifications(
take,
skip,
searched
)
when (response) {
is Resource.Success -> emit(response.data)
is Resource.Error -> { }
else -> { }
}
}
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), replay = 1)
fun setSearchedNotificationsParameters(take: Int, skip: Int) {
notificationsTakeAndSkip.tryEmit(take to skip)
}