Переупорядочиваемый список Flutter возвращается в исходное состояние - PullRequest
1 голос
/ 09 июля 2020

Я сделал список переупорядочиваемым, но теперь он возвращается в исходное состояние. Кто-нибудь может мне помочь? Мой список состоит из List Tile, который создается из базы данных с помощью Asynsnapshot. Ключ, который я использовал, такой же, как индекс. Похоже, что функция вставки не вставляет заметку в новый индекс. Это потому, что построитель будущего перестраивает?

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);
      });
   
  }

Я пробовал добавить будущую задержку, но без толку. enter image description here enter image description hereenter image description here введите описание изображения здесь

Ответы [ 2 ]

1 голос
/ 09 июля 2020

Вы можете скопировать и вставить полный код ниже
Вам не нужно снова звонить databaseHelper.getNoteList() in _onReorder
Вы можете использовать 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,
                          );
                        }
                      }))
            ],
          )),
    );
  }
}
0 голосов
/ 09 июля 2020

Внутри вашего метода _onReorder вы создаете новую переменную snapshot, а затем изменяете эту переменную. После выхода из команды _onReorder эта переменная local snapshot полностью удаляется. Таким образом, любые мутации, которые вы применяете к этой локальной переменной snapshot, также отбрасываются.

Ваша путаница заключается в том, что у вас есть две совершенно разные переменные snapshot, которые не связаны друг с другом: они имеют только одни и те же название. Другими словами, изменения, примененные к переменной snapshot в _onReorder, не влияют на переменную в build(BuildContext context).

Вам нужно ссылаться на одну переменную, чтобы отслеживать состояние порядка вашего списка .

Я воспроизвел, как это можно сделать, используя переменную состояния и initState для инициализации переменной состояния из Future:

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 использует ключ, чтобы определить, нужно ли перестраивать виджет с определенным индексом. Вместо этого используйте ключ, уникальный для содержимого виджета, например item.title в вашем случае.

...