Flutter Reorderable List 回到原来的状态

Flutter Reorderable List going back to it's original state

我使列表可重新排序,但现在它又回到了初始状态。有人能帮我吗?我的列表由使用 Asynsnapshot 从数据库生成的 List Tile 组成。我使用的密钥与索引相同。插入函数似乎没有在新索引中插入注释。是因为未来的建设者正在重建吗?

body: Container(
          padding: EdgeInsets.all(8.0),
          child: ListView(
            children: <Widget>[
              SizedBox(
                  height: MediaQuery.of(context).size.height * 0.882,
                  child: FutureBuilder(
                      future: databaseHelper.getNoteList(),
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        if (snapshot.data == null) {
                          return Text('Loading');
                        } else {
                          if (snapshot.data.length < 1) {
                            return Center(
                              child: Text('No Messages, Create New one'),
                            );
                          }
                          return ReorderableListView(
                            children: List.generate(
                              snapshot.data.length,
                              (index) {
                                return ListTile(
                                  key: Key('$index'),
                                  title: Text(
                                    snapshot.data[index].title,
                                    style: TextStyle(
                                      fontWeight: FontWeight.bold,
                                      fontSize: 20,
                                    ),
                                  ),
                                  subtitle: Text(snapshot.data[index].note,
                                      maxLines: 4),
                                  trailing: InkWell(
                                    child: Icon(Icons.add_box,
                                        color: Colors.green),
                                    onTap: () {
                                      TextEditingController txt =
                                          TextEditingController();

                                      txt.text = snapshot.data[index].note;
                                      print(txt);
                                      Route route = MaterialPageRoute(
                                          builder: (context) =>
                                              MyHomePage(custMessage: txt));
                                      Navigator.push(context, route);
                                      // addNewMessageDialog(txt);
                                    },
                                  ),
                                  // isThreeLine: true,
                                  onTap: () {
                                    Route route = MaterialPageRoute(
                                        builder: (context) => AddNote(
                                              note: snapshot.data[index],
                                            ));
                                    Navigator.push(context, route);
                                  },
                                );
                              },
                            ).toList(),
                            onReorder: _onReorder,
                          );
                        }
                      }))
            ],
          )),

重读器功能

void _onReorder(int oldIndex, int newIndex) async {
    var snapshot = await databaseHelper.getNoteList();

    if (newIndex > snapshot.length) newIndex = snapshot.length;
    if (oldIndex < newIndex) newIndex -= 1;
   
      setState(() {
        final Note item = snapshot[oldIndex];
        snapshot.removeAt(oldIndex);

        print(item.title);
        snapshot.insert(newIndex, item);
      });
   
  }

我尝试添加未来延迟但没有用。

您可以复制粘贴 运行 下面的完整代码
您不需要在 _onReorder 中再次调用 databaseHelper.getNoteList()
您可以使用noteList = snapshot.data;并操作noteList

代码片段

void _onReorder(int oldIndex, int newIndex) async {
    if (newIndex > noteList.length) newIndex = noteList.length;
    if (oldIndex < newIndex) newIndex -= 1;

    setState(() {
      final Note item = noteList[oldIndex];
      noteList.removeAt(oldIndex);

      print(item.title);
      noteList.insert(newIndex, item);
    });
  }
...
noteList = snapshot.data;
      return ReorderableListView(

工作演示

完整代码

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class Note {
  String title;
  String note;

  Note({this.title, this.note});
}

class databaseHelper {
  static Future<List<Note>> getNoteList() {
    return Future.value([
      Note(title: "1", note: "n1"),
      Note(title: "2", note: "n2"),
      Note(title: "3", note: "n3"),
      Note(title: "4", note: "n4"),
      Note(title: "5", note: "n5")
    ]);
  }
}

class _MyHomePageState extends State<MyHomePage> {
  List<Note> noteList = [];
  Future<List<Note>> _future;

  void _onReorder(int oldIndex, int newIndex) async {
    if (newIndex > noteList.length) newIndex = noteList.length;
    if (oldIndex < newIndex) newIndex -= 1;

    setState(() {
      final Note item = noteList[oldIndex];
      noteList.removeAt(oldIndex);

      print(item.title);
      noteList.insert(newIndex, item);
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _future = databaseHelper.getNoteList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
          padding: EdgeInsets.all(8.0),
          child: ListView(
            children: <Widget>[
              SizedBox(
                  height: MediaQuery.of(context).size.height * 0.882,
                  child: FutureBuilder(
                      future: _future,
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        if (snapshot.data == null) {
                          return Text('Loading');
                        } else {
                          if (snapshot.data.length < 1) {
                            return Center(
                              child: Text('No Messages, Create New one'),
                            );
                          }

                          noteList = snapshot.data;
                          return ReorderableListView(
                            children: List.generate(
                              snapshot.data.length,
                              (index) {
                                return ListTile(
                                  key: Key('$index'),
                                  title: Text(
                                    snapshot.data[index].title,
                                    style: TextStyle(
                                      fontWeight: FontWeight.bold,
                                      fontSize: 20,
                                    ),
                                  ),
                                  subtitle: Text(snapshot.data[index].note,
                                      maxLines: 4),
                                  trailing: InkWell(
                                    child: Icon(Icons.add_box,
                                        color: Colors.green),
                                    onTap: () {
                                      /*TextEditingController txt =
                                      TextEditingController();

                                      txt.text = snapshot.data[index].note;
                                      print(txt);
                                      Route route = MaterialPageRoute(
                                          builder: (context) =>
                                              MyHomePage(custMessage: txt));
                                      Navigator.push(context, route);*/
                                      // addNewMessageDialog(txt);
                                    },
                                  ),
                                  // isThreeLine: true,
                                  onTap: () {
                                    /*Route route = MaterialPageRoute(
                                        builder: (context) => AddNote(
                                          note: snapshot.data[index],
                                        ));
                                    Navigator.push(context, route);*/
                                  },
                                );
                              },
                            ).toList(),
                            onReorder: _onReorder,
                          );
                        }
                      }))
            ],
          )),
    );
  }
}

在您的 _onReorder 方法中,您创建了一个新的 snapshot 变量,然后改变该变量。一旦 _onReorder 退出,这个 local snapshot 变量就被完全丢弃了。因此,您应用于此本地 snapshot 变量的任何变更也将被丢弃。

你的困惑在于你有两个完全不同的 snapshot 变量,它们彼此没有耦合:它们只是共享相同的名称。换句话说,应用于 _onReorder 中的 snapshot 变量的更改对 build(BuildContext context) 中的变量没有影响。

您需要引用单个变量来跟踪列表顺序的状态。

我已经重现了如何通过使用状态变量和 initStateFuture:

初始化状态变量来做到这一点
import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: Scaffold(body: Body())));

class Body extends StatefulWidget {
  @override
  _BodyState createState() => _BodyState();
}

class _BodyState extends State<Body> {
  List<String> snapshot;
  @override
  void initState() {
    super.initState();
    initializeSnapshot();
  }

  Future initializeSnapshot() async {
    final list = await getListFromDatabase();
    setState(() => snapshot = list);
  }

  Future getListFromDatabase() async {
    // In reality, you would make some network call here.
    return ["a", "b", "c"];
  }

  @override
  Widget build(BuildContext context) => snapshot == null
      ? Center(child: CircularProgressIndicator())
      : ReorderableListView(
          onReorder: (oldIndex, newIndex) {
            if (newIndex > snapshot.length) newIndex = snapshot.length;
            if (oldIndex < newIndex) newIndex -= 1;

            setState(() {
              final String item = snapshot[oldIndex];
              snapshot.removeAt(oldIndex);
              snapshot.insert(newIndex, item);
            });
          },
          children: snapshot
              .map((x) => ListTile(key: ValueKey(x), title: Text(x)))
              .toList(),
        );
}

另外:不要将列表中项目的索引用作小部件的 Key。这是因为 Flutter 使用键来确定特定索引处的小部件是否需要重建。相反,使用小部件的 contents 唯一的密钥,例如您的 item.title