【问题标题】:Looking up a deactivated widget's ancestor is unsafe using provider and snackbar使用提供程序和快餐栏查找已停用小部件的祖先是不安全的
【发布时间】:2020-11-18 12:02:20
【问题描述】:

我正在使用 DismissibleWidget 从列表中删除注释。当注释被删除时,会调用一个 Snackbar 以让用户有机会撤消该操作。单击按钮后,将注释重新插入到列表中时,会出现此错误:

在处理手势时抛出以下断言: 查找已停用小部件的祖先是不安全的。 此时小部件的元素树的状态不再稳定。

  1. 可关闭的小部件

                 Dismissible(
                    direction: DismissDirection.endToStart,
                    onDismissed: (direction){
                      var removedNote = list.notes[index];
                      Provider.of<ListProvider>(context, listen: false).removeNote(index);
    
                      Scaffold.of(context).showSnackBar(
                          SnackBar(
                            content: Text("Nota removida"),
                            action: SnackBarAction(
                              label: "Desfazer",
                              onPressed: (){
                                Provider.of<ListProvider>(context, listen: false).insertNote(removedNote, index);
                              },
                            ),
                            duration: Duration(seconds: 3),
                          ),
                      );
                    },
    

    ...

  2. 提供者中的方法

    void insertNote(NoteModel note, int index){
       notes.insert(index, note);
       fileRepository.saveToFile(notes);
       notifyListeners();
    

    }

【问题讨论】:

    标签: flutter dart flutter-provider


    【解决方案1】:

    我遇到了一些问题,但使用 BLoC 作为状态管理,我的解决方案是从该小部件上方获取上下文。

    出了什么问题?

    您试图寻找不再可用的上下文。这也是因为variable shadowing

    解决方案?

    到达该小部件上方的内容。

    伪颤振代码

    class NameOfYourClass{
        build(BuildContext context1) {
          return ListView.builder(
              itemBuilder: (context2, index) {
                 return MyItem(); 
              }
          );
        }
       }
    

    假设您使用Dismissible 小部件关闭MyItemcontext2 将不再可用,如果您打印context2,它将看起来像这样(注意 :当MyItem 被解雇时):

    SliverList(delegate: SliverChildBuilderDelegate#66afb(estimated child count: 1), renderObject: RenderSliverList#593ed relayoutBoundary=up2 DETACHED)
    

    如您所见,该项目是树中的DETACHED。如果您打印 context1,它将看起来像这样。

    NameOfYourClass
    

    总之,不要这样做:

     Provider.of<ListProvider>(context2, listen: false).insertNote(removedNote, index);
    

    这样做:

     Provider.of<ListProvider>(context1, listen: false).insertNote(removedNote, index);
    

    不要使用 context1 或 context2,这是为了说明目的。

    【讨论】:

    • 如果你还不太明白,让我知道用Provider制作一个可重现的示例代码。
    猜你喜欢
    • 2020-12-26
    • 2020-08-08
    • 2021-07-28
    • 2021-11-15
    • 2021-06-03
    • 2022-06-26
    • 2021-04-29
    • 1970-01-01
    • 2021-11-08
    相关资源
    最近更新 更多