Flutter GetX列表筛选问题:退格后已过滤项无法恢复
Flutter GetX 实时筛选列表问题
我正在开发首个Flutter应用,尝试用GetX结合TextFormField对从API获取的TreeTypes列表进行实时筛选。目前功能仅部分生效:不符合搜索字符串的项能被正确过滤,但退格删除搜索字符时,已被过滤的项无法重新回到列表中。我明白需要基于原始列表而非已过滤后的列表进行筛选,但尝试多种方法后仍未解决问题。
以下是我的TreeTypeController和视图代码:
TreeTypeController 代码
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:bonsai_care_app/services/tree_type_service.dart'; import 'package:bonsai_care_app/models/tree_type.dart'; class TreeTypeController extends GetxController { dynamic arguments = Get.arguments; var treeTypeList = <TreeType>[].obs; var isLoaded = true.obs; @override void onInit() { super.onInit(); fetchAndSetTreeTypeList(arguments); } void filterTreeTypes(searchString) { var filteredTreeTypeList = []; filteredTreeTypeList = treeTypeList .where((element) => element.name.toLowerCase().contains(searchString.toLowerCase())) .toList(); print(filteredTreeTypeList.length); treeTypeList(filteredTreeTypeList); } Future<void> fetchAndSetTreeTypeList(arguments) async { debugPrint('TreeTypesController fetchTreeTypes()'); try { isLoaded(false); var tree_types = await TreeTypeService().fetchTreeTypes(arguments); if (tree_types != null) { treeTypeList(tree_types); } } catch (error) { debugPrint(error); throw (error); } finally { isLoaded(true); } } }
视图代码
import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:bonsai_care_app/controllers/tree_type_controller.dart'; import 'package:bonsai_care_app/views/select_tree_type_details_screen.dart'; class SelectTreeTypeResultsScreen extends StatelessWidget { final TreeTypeController treeTypeController = Get.put(TreeTypeController()); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('select_tree_type_results__heading'.tr), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Obx( () { return Column( children: [ Container( child: TextFormField( onChanged: (query) { treeTypeController.filterTreeTypes(query); }, decoration: InputDecoration( labelText: 'select_tree_type_results__search_input_label'.tr, border: const OutlineInputBorder(), ), ), ), Container( height: 500, width: 200, child: Visibility( visible: treeTypeController.isLoaded.value, replacement: Center( child: CircularProgressIndicator(), ), child: treeTypeController.treeTypeList.length == 0 ? Center( child: Text('no_results'.tr), ) : ListView.builder( itemCount: treeTypeController.treeTypeList.length, itemBuilder: (context, index) { return ListTile( title: Text(treeTypeController .treeTypeList[index].name), onTap: () { Get.to(() => SelectTreeTypeDetailsScreen(), arguments: treeTypeController .treeTypeList[index]); }, ); }, ), ), ), ], ); }, ), ], ), ); } }
问题根源
当前treeTypeList既承担原始数据存储,又作为过滤后数据的展示载体。每次筛选时,过滤结果直接覆盖了原始数据,导致退格时无法找回之前被过滤的项。
修复方案
在控制器中新增变量存储原始数据,筛选仅基于原始数据处理,更新用于展示的列表即可:
修改后的TreeTypeController
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:bonsai_care_app/services/tree_type_service.dart'; import 'package:bonsai_care_app/models/tree_type.dart'; class TreeTypeController extends GetxController { dynamic arguments = Get.arguments; // 存储API获取的原始数据,仅初始化时赋值 final _originalTreeTypeList = <TreeType>[].obs; // 用于UI展示的过滤后列表 var treeTypeList = <TreeType>[].obs; var isLoaded = true.obs; @override void onInit() { super.onInit(); fetchAndSetTreeTypeList(arguments); } void filterTreeTypes(String searchString) { if (searchString.isEmpty) { // 搜索为空时还原为原始列表 treeTypeList.assignAll(_originalTreeTypeList); return; } var filteredTreeTypeList = _originalTreeTypeList .where((element) => element.name.toLowerCase().contains(searchString.toLowerCase())) .toList(); print(filteredTreeTypeList.length); treeTypeList.assignAll(filteredTreeTypeList); } Future<void> fetchAndSetTreeTypeList(arguments) async { debugPrint('TreeTypesController fetchTreeTypes()'); try { isLoaded(false); var tree_types = await TreeTypeService().fetchTreeTypes(arguments); if (tree_types != null) { _originalTreeTypeList.assignAll(tree_types); // 初始化时展示列表与原始列表一致 treeTypeList.assignAll(tree_types); } } catch (error) { debugPrint(error.toString()); throw error; } finally { isLoaded(true); } } }
关键修改点
- 新增
_originalTreeTypeList存储原始数据,后续不修改 - 筛选逻辑基于原始数据执行,结果赋值给
treeTypeList用于展示 - 搜索字符串为空时,直接将原始列表赋值给展示列表实现还原
- 使用
assignAll方法更新Observable列表,确保GetX能正确监听数据变化
视图代码无需修改,保持原有逻辑即可。
内容的提问来源于stack exchange,提问作者Reinier
相关产品推荐
相关产品推荐

