【问题标题】:Flutter Dismissible Widget re shows the widget after dismissingFlutter Dismissible Widget 重新显示关闭后的小部件
【发布时间】:2020-09-10 17:05:02
【问题描述】:

我正在尝试创建一个列表,在该列表中拖动时可以删除其磁贴,因此我使用了 Dismissible 小部件,一切都按我的意愿工作,但是当拖动磁贴以将其关闭时,磁贴会重新显示片刻,然后消失,我的意思的演示显示在这个video

FutureBuilder(
        future: getMyFavData(),
        builder: (context, snapshot) {
          if (snapshot.data == null)
            return Container(
                child: Center(
                    child: CircularProgressIndicator(
              backgroundColor: Colors.red,
            )));
          else
            return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (context, index) {
                  var monthOfProductList =
                      snapshot.data.elementAt(index)['date'].toDate().month;
                  var monthNow = DateTime.now().month;
                  bool newItem = false;
                  if (monthNow - monthOfProductList == 0) {
                    newItem = true;
                  }
                  return Dismissible(
                    key: UniqueKey(),
                    onDismissed: (direction) async  {
                      if (direction == DismissDirection.startToEnd) {

                        await deleteFromDataBase(
                            snapshot.data.elementAt(index).documentID);

                        setState(() {
                          snapshot.data.remove(index);
                        });

                      }
                    },
                    background: Container(
                      color: Colors.red,
                      child: Row(
                        children: [
                          Icon(
                            Icons.delete_forever,
                            color: Colors.white,
                            size: 100,
                          ),
                        ],
                      ),
                    ),
                    direction: DismissDirection.startToEnd,
                    child: GestureDetector(
                      onTap: () {

                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => ProductFullScreenView(
                                      productInfo: snapshot.data.elementAt(index),
                                    )));
                      },
                      child: ProductListCardVerticalFavorite(),
                    ),
                  );
                });
        });

我不知道问题出在哪里,任何帮助将不胜感激

【问题讨论】:

    标签: flutter dart flutter-widget dismissible


    【解决方案1】:

    您应该避免在构建方法中分配未来。在 initState 中保存一个实例,因为每次构建树都会重新构建未来。

    Future myCachedFuture;
      @override
      void initState() {
        super.initState();
    
        myCachedFuture = getMyFavData();
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(future: myCachedFuture,)
      }
    

    【讨论】:

    • 我将开始使用它,非常感谢 gauris
    【解决方案2】:

    您使用FutureBuilder 获取数据列表并在onDismissed 上将其删除。

    当您关闭一个项目时,包含它的小部件将再次重建,因此您无需调用setState

    此外,当您调用删除函数 (deleteFromDataBase) 时,这将删除一些真实保存的数据,因此您不需要从您获取的数据中删除它,因为这里当一个项目被删除时,将调用一个函数也将它从真实保存的数据中删除,小部件将被重建,另一个调用 (getMyFavData()) 将在保存的数据上发生以获取它们,但这次结果是前一个没有删除项目的所有结果。

    我用你的代码做了一个简单的例子,并做了一个假的未来调用:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(Home());
    }
    
    class Home extends StatefulWidget {
      @override
      _HomeState createState() => _HomeState();
    }
    
    class _HomeState extends State<Home> {
      List<String> lst = [
        '1',
        '2',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9',
        '10',
        '11',
      ];
      Future<List<String>> getMyFavData() async {
        return Future.value(lst);
      }
    
      Future<void> deleteFromDataBase(int index) async {
        Future.delayed(Duration(milliseconds: 500)).then((_) {
          lst.removeAt(index);
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: FutureBuilder(
                future: getMyFavData(),
                builder: (context, snapshot) {
                  if (snapshot.data == null)
                    return Container(
                      child: Center(
                        child:
                            CircularProgressIndicator(backgroundColor: Colors.red),
                      ),
                    );
                  else
                    return ListView.builder(
                        itemCount: snapshot.data.length,
                        itemBuilder: (context, index) {
                          return Dismissible(
                              key: UniqueKey(),
                              onDismissed: (direction) async {
                                if (direction == DismissDirection.startToEnd) {
                                  await deleteFromDataBase(index);
                                }
                              },
                              background: Container(
                                color: Colors.red,
                                alignment: Alignment.centerLeft,
                                child: Icon(
                                  Icons.delete_forever,
                                  color: Colors.white,
                                ),
                              ),
                              direction: DismissDirection.startToEnd,
                              child: Container(
                                width: MediaQuery.of(context).size.width,
                                child: Text(lst[index]),
                                color: Colors.blue,
                                margin: EdgeInsets.all(5.0),
                              ));
                        });
                }),
          ),
        );
      }
    }
    
    

    【讨论】:

    • 非常感谢您的解释,我对您的代码的问题是,当我的列表被点击时,它将导航到产品的全屏,但是当从全屏返回到收藏夹时通过后退按钮,可关闭的小部件将显示一条错误消息,提示“已关闭的可关闭小部件仍然是树的一部分。”我通过在按下时导航到全屏之前调用 setState() 来解决它。
    • 不客气,我做了一个导航,我没有收到任何错误,如果你喜欢你可以打开一个新问题或添加更多关于数据和功能的信息,我'很乐意提供帮助。
    • 现在一切都好,如果它工作我宁愿不碰它哈哈哈再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 2020-12-16
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多