如何修复Jetpack Compose加密货币列表的搜索功能?
修复加密货币列表应用的搜索功能
问题根源
当前搜索功能失效的核心原因:
- UI展示依赖
viewModel.state.value.coins,但搜索函数操作的是独立的coinsList变量,数据源不统一导致搜索结果无法同步到UI - API加载数据后,搜索相关的缓存列表未同步真实数据,导致搜索时无有效数据可过滤
修复步骤
1. 调整状态数据类结构
将缓存列表整合到CoinListState中,确保数据源统一:
data class CoinListState( val isLoading: Boolean = false, val coins: List<Coin> = emptyList(), val cachedCoins: List<Coin> = emptyList(), val error: String = "" )
2. 重写ViewModel的搜索逻辑
更新ViewModel,同步API数据到缓存列表,修改过滤规则(支持排名部分匹配),并直接更新UI绑定的状态字段:
@HiltViewModel class CoinListViewModel @Inject constructor( private val getCoinsUseCase: GetCoinsUseCase, ) : ViewModel() { private val _state = mutableStateOf(CoinListState()) val state: State<CoinListState> = _state init { getCoins() } fun searchCoinsList(query: String) { viewModelScope.launch(Dispatchers.Default) { val trimmedQuery = query.trim() // 优先使用缓存的完整数据作为搜索源 val searchSource = _state.value.cachedCoins.ifEmpty { _state.value.coins } val filteredCoins = if (trimmedQuery.isEmpty()) { // 清空搜索时恢复完整列表 _state.value.cachedCoins.ifEmpty { _state.value.coins } } else { searchSource.filter { coin -> // 匹配名称(忽略大小写)、排名(支持部分数字匹配)、符号(忽略大小写) coin.name.contains(trimmedQuery, ignoreCase = true) || coin.rank.toString().contains(trimmedQuery) || coin.symbol.contains(trimmedQuery, ignoreCase = true) } } // 更新UI状态 _state.value = _state.value.copy(coins = filteredCoins) } } private fun getCoins() { getCoinsUseCase().onEach { result -> when (result) { is Resource.SUCCESS -> { val coinList = result.data ?: emptyList() _state.value = CoinListState( coins = coinList, cachedCoins = coinList // 初始化完整数据缓存 ) } is Resource.ERROR -> { _state.value = CoinListState( error = result.message ?: "An unexpected error occurred" ) } is Resource.LOADING -> { _state.value = CoinListState(isLoading = true) } } }.launchIn(viewModelScope) } }
3. 功能验证
修改后搜索功能可正常工作:
- 输入币种名称(如
Bitcoin)会匹配包含该名称的结果 - 输入排名数字(如
1或10)会匹配排名包含对应数字的币种 - 输入币种符号(如
BTC)会匹配包含该符号的结果 - 清空搜索框会自动恢复展示完整币种列表
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

