在 ListView 上应用多个条件过滤器

apply multiple conditional filters on a ListView

我是一名新的 flutter 开发人员,想在我的列表中使用多个过滤器。 我正在使用 ListView :


ListView.builder(
itemBuilder: (ctx, index) =>
MealCard(_customList[index]),
itemCount: _customList.length,
                          ),

和我的膳食 class 具有以下属性:

 Meal {
final String id,
final String title, 
final String imgUrl, 
final bool isLowCalorie,
final bool isVegan,
final bool isBreakfat, 
final bool isDinner,
final bool isLunch}

我想根据 class 中包含的布尔值应用不同的过滤器;我有一些看起来像这样的方法:

 List<Meal> get breakfastFilter {
    return _meals.where((element) => element.isBreakfast).toList();
  }

  List<Meal> get lunchFilter {
    return _meals.where((element) => element.isLunch).toList();
  }

  List<Meal> get dinnerFilter {
    return _meals.where((element) => element.isDinner).toList();

但是这些方法允许我创建一个列表,如果我想一起添加额外的过滤器并创建两个列表的组合怎么办。

你可以这样做:

 bool filterItem(element){
    return element.isVegan&&element.isBreakfat;
  }
    
  _meals.where((element) => filterItem(element)).toList();  

有很多方法可以做到这一点,但您可以尝试将布尔值与可选参数结合使用,如下所示:

getMealFilter(_meals,
    {bool lookForBreakfast = false,
    bool lookForVegan = false,
    bool lookForLunch = false}) {
  return _meals
      .where((element) =>
          (lookForBreakfast && element.isBreakfast) ||
          (lookForVegan && element.isBreakfast) ||
          (lookForLunch && element.isLunch))
      .toList();
}

我只放了 3 个过滤器,但您可以轻松添加其余部分。这是如何工作的,例如,如果 lookForBreakfast 为假,则忽略 element.isBreakfast。 (false 和 something 总是 false),其他参数依此类推。

我知道我迟到了,所以让我来表彰一下吧。我会稍微重构它以支持多个过滤器,否则您不会预先知道将应用多少个过滤器。

我会创建一个名为 MealType:

的枚举
enum MealType {
  none,
  isLowCalorie,
  isVegan,
  isBreakfast,
  isDinner,
  isLunch
}

重构 class 以获取 MealType 值的列表:

class Meal {
  final String? id;
  final String? title;
  final String? imgUrl;
  final List<MealType>? mealTypeFilter;
  
  Meal({ this.id, this.title, this.imgUrl, this.mealTypeFilter });  
}

数据将如下所示:

List<Meal> meals = [
    Meal(
      id: '1001',
      title: 'Pancakes',
      imgUrl: '',
      mealTypeFilter: [
        MealType.isBreakfast
      ]
    ),
    Meal(
      id: '1002',
      title: 'Chicken Wings',
      imgUrl: '',
      mealTypeFilter: [
        MealType.isLunch
      ]
    ),
    Meal(
      id: '1003',
      title: 'Yogurt',
      imgUrl: '',
      mealTypeFilter: [
        MealType.isLowCalorie,
        MealType.isBreakfast,
        MealType.isVegan
      ]
    )
  ];

我会在 Set 中收集应用的过滤器以避免重复,并过滤餐食 mealTypeFilter 集合是否包含任何应用的过滤器:


Set<MealType> appliedFilters = {};
  List<Meal> filteredList = [];
  
  List<Meal> getFilteredList() {
    if (appliedFilters.isEmpty) {
      return meals;
    }
    
    return meals.where((m) => m.mealTypeFilter!.any((f) => appliedFilters.contains(f))).toList();
  }

当我触发包含要应用的过滤器的按钮并填充 时,每次在构建方法中我都会调用 getFilteredList() 方法filteredList 我用它来渲染 ListView 结果:

@override
Widget build(BuildContext context) {
    
    filteredList = getFilteredList();
    
    // rest of the code here
}

请参阅 Gist 了解完整代码,并通过 DartPad 运行 查看它的实际效果,如下所示:

希望这能奏效。