如何获取索引值而不在 ListView.builder 内重复?

How to get the index value whilst not getting duplicates within ListView.builder?

我试图仅在用户输入支出信息时显示本周的预算支出和时间表。

这是预期的结果,一切似乎都运行良好,直到我每周增加不止一笔支出。

情况如下:

我理解的问题是 ListView.builder 获取“初始”和“结束”之间的日期并构建小部件。因此,因为在这些日期之间有 2 次支出,所以它会构建其中的 2 个小部件。问题是我似乎想不出一种不重复地展示它们的方法。

这是我的代码:

Widget build(BuildContext context) {
    return ListView.builder(
      shrinkWrap: true,
      controller: ScrollController(),
      itemCount: snapshot.data!.length,
      padding: const EdgeInsets.only(bottom: 8),
      itemBuilder: (context, index) {
        final spending = snapshot.data![index];

        DateTime spendingDate = DateTime.parse(spending.date);
        var initial =
            DateTime(initialDate.year, initialDate.month, initialDate.day - 1);
        var end = DateTime(endDate.year, endDate.month, endDate.day + 1);

        return spendingDate.isAfter(initial) && spendingDate.isBefore(end)
            ? Column(
                children: [
                  WeekDivider(label: label, dateEstimation: dateEstimation),
                  WeeklySpendingStream(
                    color: color,
                    snapshot: snapshot,
                    initialDate: initialDate,
                    endDate: endDate,
                  ),
                ],
              )
            : const SizedBox();
      },
    );
  }

WeeklySpendingStreamCode:

Widget build(BuildContext context) {
    return ListView.builder(
      shrinkWrap: true,
      controller: ScrollController(),
      itemCount: snapshot.data!.length,
      padding: const EdgeInsets.only(bottom: 8),
      itemBuilder: (context, index) {
        final spending = snapshot.data![index];

        DateTime spendingDate = DateTime.parse(spending.date);
        var initial =
            DateTime(initialDate.year, initialDate.month, initialDate.day - 1);
        var end = DateTime(endDate.year, endDate.month, endDate.day + 1);

        if (spendingDate.isAfter(initial) && spendingDate.isBefore(end)) {
          return SwipeActionCell(
            editModeOffset: 0,
            fullSwipeFactor: 0.50,
            key: ObjectKey(snapshot.data![index]),
            trailingActions: [
              SwipeAction(
                performsFirstActionWithFullSwipe: true,
                color: Colors.transparent,
                content: Container(
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(30),
                      color: Colors.red,
                    ),
                    child: getIconButton(Colors.red, IconlyBold.delete)),
                onTap: (handler) async {
                  handler(true);
                  await Future.delayed(const Duration(milliseconds: 100));
                  snapshot.data!.removeAt(index);
                  SpendingDatabaseHelper.instance.removeMethod(spending.id!);
                },
              ),
            ],
            child: SpendingCard(
              beneficiary: spending.beneficiary,
              budgetSpent: currency.format(int.parse(spending.budgetSpent)),
              date: DateFormat("dd-MM-yyyy")
                  .format(DateTime.parse(spending.date)),
              colorValue: color,
            ),
          );
        } else {
          return const SizedBox();
        }
      },
    );
  }

snapshot.data的输出:

[
{id: 8, budgetName:  Food & Beverage, beneficiary: ddd, budgetSpent: 1, date: 2022-02-21}, 
{id: 7, budgetName:  Food & Beverage, beneficiary: dfgvsd, budgetSpent: 1, date: 2022-02-14}, 
{id: 4, budgetName:  Food & Beverage, beneficiary: ddd, budgetSpent: 1, date: 2022-02-11}, 
{id: 10, budgetName:  Food & Beverage, beneficiary: ddd, budgetSpent: 1, date: 2022-02-11}, 
{id: 5, budgetName:  Food & Beverage, beneficiary: asxasd, budgetSpent: 1, date: 2022-02-06}
]

非常感谢 suggestions/ideas 如何解决这个问题。 提前致谢!

没关系,我通过使用“.where”获取数据并检查它是否为空以某种方式找到了解决方案。效果很好。

var initial = DateTime(initialDate.year, initialDate.month, initialDate.day - 1);
    var end = DateTime(endDate.year, endDate.month, endDate.day + 1);

    final spending = snapshot.data!.where((s) =>
        DateTime.parse(s.date).isAfter(initial) &&
        DateTime.parse(s.date).isBefore(end));

    return spending.isNotEmpty ||
            DateTime.now().isAfter(initial) && DateTime.now().isBefore(end)
        ? spending.isEmpty
            ? Column(
                children: [
                  WeekDivider(label: label, dateEstimation: dateEstimation),
                  const Padding(
                    padding: EdgeInsets.only(top: 8, bottom: 16),
                    child: Text(
                      'No spending this week',
                      style: kCaption,
                    ),
                  ),
                ],
              )
            : ListView(
                shrinkWrap: true,
                controller: ScrollController(),
                padding: const EdgeInsets.only(bottom: 8),
                children: [
                  Column(
                    children: [
                      WeekDivider(label: label, dateEstimation: dateEstimation),
                      WeeklySpendingStream(
                        color: color,
                        snapshot: snapshot,
                        initialDate: initialDate,
                        endDate: endDate,
                      ),
                    ],
                  )
                ],
              )
        : const SizedBox();
  }

我认为您提出的问题是因为您只是提取数据库文件而不进行过滤,所以请使用 .toSet() 或将提取的数据分配给变量作为映射或 Set 并使用 .toSet()。