如何通过debounce修正调用API搜索请求?

问题描述 投票:0回答:1

我尝试使用去抖动设置正确的 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 请求。预计用户取消输入后只能有一个带有此参数的请求,并且延迟会超过。

android kotlin search android-jetpack-compose debouncing
1个回答
0
投票

正如 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)
}
© www.soinside.com 2019 - 2024. All rights reserved.