【问题标题】:valuenotifier not updating the widget on udating the listvaluenotifier 在更新列表时未更新小部件
【发布时间】:2021-08-17 04:58:25
【问题描述】:
import 'package:flutter/material.dart';
import '../../Data/Globalvariable.dart' as global;

class MenuBar extends StatefulWidget {
  final key = UniqueKey();
  // final pin;
  // MenuBar({this.pin='112'});
  @override
  _MenuBarState createState() {
    return _MenuBarState();
  }
}

class _MenuBarState extends State<MenuBar> {
  ValueNotifier<List<String>> st = ValueNotifier(global.pincode);
  Widget total() {
    return ListView.builder(
      itemCount: global.pincode.length,
      itemBuilder: (context, index) {
        final item = global.pincode[index];
        return Dismissible(
          key: UniqueKey(),
          onDismissed: (direction) {
            setState(() {
              global.pincode.removeAt(index);
            });
            ScaffoldMessenger.of(context)
                .showSnackBar(SnackBar(content: Text('$item Removed')));
          },
          background: Container(color: Colors.red),
          child: ListTile(
            title: Text(item),
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      builder: (context, n, menu) {
        print(global.pincode);
        return total();
      },
      child: total(),
      valueListenable: st,
    );
  }
}

这是我的主文件我有一个全局文件 我所有的工作变量都在那里

Globalvariable.dart

library project.globals;
List<String> pincode = ['Select Pin','110084','110088'];

现在我将数据添加到 pincode valuenotifier 应该听它并自动更新小部件但它没有这样做我验证使用调试控制台它会在我调用 setstate 时得到更新,这没问题,但我想更新小部件为我将数据添加到我的列表中

这是为了证明我在上面所说的 wigdet 在移除时更新,而不是在添加时更新

【问题讨论】:

  • 使用 st.notifyListeneres() 代替 setState !
  • 我认为您必须以某种方式在ValueListenableBuilder builder 中使用st,例如return total(st),否则无论st 的值如何,它都会返回相同的结果。
  • 这是我第三次看到这种误解,你的ValueNotifier&lt;List&lt;SomeType&gt;&gt;不会知道值什么时候改变了。查看ValueNotifier的来源,它使用了相等运算符==。这不适用于列表,您正在将相同的列表指针与其自身进行比较(即使列表的内容已更改)。在 Dart stackoverflow.com/a/22333042/10830091 的列表比较中查看此答案
  • 首先让我们解决这个问题。您不能像 global.pincode.removeAt(index); 那样更新您的列表。你必须st 而不是st.value.removeAt(index);
  • 在你解决了这个问题之后。您有 2 个解决方案。 A. 强行告诉 ValueNotifier 其值已更改st.value = List.from(st.value)..removeAt(index); B. 子类 ValueNotifier 并定义用于在列表中添加/删除元素的方法,在所述方法中手动调用 notifyListeners。

标签: flutter dart


【解决方案1】:

如果您将ValueNotifier 与列表一起使用,则应使用st.value.add() 附加到该列表st,除非您将该全局列表设为ValueNotifier,否则修改global.pincode 列表将不会反映出来。

所以你要么拥有st.value.add(),要么在你的全局文件ValueNotifier&lt;List&lt;String&gt;&gt; pincode = ValueNotifier(&lt;String&gt;[...]); 中使用valueListenable: global.pincode 并使用global.pincode.value.xyz 进行修改

【讨论】:

  • 这是解决方案的一部分,是的,应该通过 ValueNotifier 对象 st 而不是全局列表 global.pincode 进行更新。解决方案的第二部分涉及列表相等性以及ValueNotifier 如何知道何时应该通知其侦听器。 ValueNotifier 通过相等(即== 运算符)将新值与旧值不同,然后如果存在差异,则会发生通知。对于列表,由于列表相等的工作方式,这将不起作用。请看我上面的 cmets。
【解决方案2】:

如果您已经使用 ValueNotifier,则不需要使用 SetState。
要更新状态,请使用:st.value = new value

因为您已经用 ValueListenableBuilder 包装了您的子小部件,所以状态将自动更改如果 st 的值发生变化。


ValueNotifier 使用相等来检测变化。对于 List,如果你只添加/删除列表的值,dart 编译器不会注意到任何变化。

要解决这个问题,您需要创建一个新列表,以便 dart 编译器检测到更改。

您可以像这样更新您的代码:

return Dismissible(
  key: UniqueKey(),
  onDismissed: (direction) {
    st.value = List.from(st.value)..removeAt(index);
    ScaffoldMessenger.of(context)
        .showSnackBar(SnackBar(content: Text('$item Removed')));
  },
  background: Container(color: Colors.red),
  child: ListTile(
    title: Text(item),
  ),
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2016-08-16
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    相关资源
    最近更新 更多