Flutter Dismissible Widget在关闭后重新显示该小部件

i am trying to make a list in which its tiles can be deleted when dragged so i used the Dismissible widget and everything is working as i wanted, however when dragging the tile to dismiss it the tile re shows for a few moment and disappear, a demo of what i mean is shown in this 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(),
                    ),
                  );
                });
        });

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

评论
  • fillum
    fillum 回复

    You used FutureBuilder to fetch a list of data and on the onDismissed you remove it.

    When you dismiss an item, the widget that holds it will rebuild again so you don't need to call the setState.

    Also when you call a remove function(deleteFromDataBase), that's going to remove some real saved data so you don't need to remove it from data you fetched because here when an item is removed a function will be called to delete it from real saved data too and the widget will be rebuilt and another call(getMyFavData()) would occur on saved data to fetch them but this time the result is all of the previous one without the removed item.

    我用您的代码做了一个简单的例子,并做了一个假的未来电话:

    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),
                              ));
                        });
                }),
          ),
        );
      }
    }
    
    
  • 你,不配我
    你,不配我 回复

    您应该避免在build方法中分配未来。将实例保存在initState中,因为每次您构建该树时,都会再次调用future。

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