sqlite - 列表项更改时Flutter ListView不会更新

标签 sqlite flutter dart sqflite

我开始学习Flutter。我正在使用它开发一个简单的应用程序。现在,我正在开发一项功能,其中我的应用程序将显示SQLite数据库中的记录,并且用户将新记录添加到SQLite数据库中。但是我的ListView显示空白屏幕。

我有一个名为DatabaseHelper的类,其中包含以下代码。

class DatabaseHelper {
  static DatabaseHelper _databaseHelper;
  Database _database;

  String noteTable = 'note_table';
  String colId = 'id';
  String colTitle = 'title';
  String colDescription = 'description';
  String colPriority = 'priority';
  String colDate = 'date';

  DatabaseHelper._createInstance();

  factory DatabaseHelper() {
    if (_databaseHelper == null) {
      _databaseHelper = DatabaseHelper._createInstance();
    }

    return _databaseHelper;
  }

  Future<Database> get database async {
    if (_database == null) {
      _database = await initializeDatabase();
    }

    return _database;
  }

  Future<Database> initializeDatabase() async {
    Directory directory = await getApplicationDocumentsDirectory();
    String path = directory.path + 'notes.db';
    var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDB);

    return notesDatabase;
  }

  void _createDB(Database db, int newVersion) async {
    await db.execute('CREATE TABLE $noteTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colTitle TEXT, $colDescription TEXT, $colPriority INTEGER, $colDate TEXT)');
  }

  Future<List<Map<String, dynamic>>> getNoteMapList() async {
    Database db = await this.database;

    return await db.query(noteTable, orderBy: '$colPriority ASC');
  }

  Future<int> insertNote(Note note) async {
    Database db = await this.database;

    return await db.insert(noteTable, note.toMap());
  }

  Future<int> updateNote(Note note) async {
    var db = await this.database;

    return await db.update(noteTable, note.toMap(), where: '$colId = ?', whereArgs: [note.id]);
  }

  Future<int> deleteNote(int id) async {
    var db = await this.database;

    return await db.rawDelete('DELETE FROM $noteTable WHERE $colId = $id');
  }

  Future<int> getCount() async {
    Database db = await this.database;
    List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT(*) FROM $noteTable');

    return Sqflite.firstIntValue(x);
  }
}

然后,我有一个名为NoteList的小部件,其中包含以下代码,其中显示了项目列表。
    class NoteList extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _NoteListState();
      }
    }

    class _NoteListState extends State<NoteList> {
      List<Note> _notes = [];
      int _count = 0;
      DatabaseHelper _databaseHelper = DatabaseHelper();

      _NoteListState() {
        this._notes = getNotes();
        this._count = _notes.length;
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text("Notes"),),
          body: Container(
            child: getListView(context),
          ),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: () {
              navigateToNoteForm("Add Note");
            },
          ),
        );
      }

      Widget getListView(BuildContext context) {
        return ListView.builder(
            itemCount: _count,
            itemBuilder: (context, index) {
              return ListTile(
                leading: CircleAvatar(
                  backgroundColor: _notes[index].priority == 1? Colors.yellow: Colors.red,
                  child: Icon(_notes[index].priority == 1 ? Icons.arrow_right : Icons.add),
                ),
                title: Text(_notes[index].title),
                subtitle: Text(_notes[index].date),
                trailing: Icon(Icons.delete),
                onTap: () {
                  navigateToNoteForm("Edit Note", _notes[index]);
                },
              );
            });
      }

      void navigateToNoteForm(String pageTitle, [Note note]) async {
        bool result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
          return NoteForm(pageTitle, note);
        }));

        if (result) {
          setState(() {
            debugPrint("Updating list");
            _notes = getNotes();
            _count = _notes.length;
          });
        }
      }

      List<Note> getNotes() {
        List<Note> notes = List<Note>();
        Future<List<Map<String, dynamic>>> notesFuture = _databaseHelper.getNoteMapList();
        notesFuture.then((notesMap) {
          debugPrint("Total notes found in the database ${notesMap.length}");
          notesMap.forEach((map) {
            notes.add(Note.fromMapObject(map));
          });
        });

        return notes;
      }
    }


Then I also have another widget class called NoteForm with the following code.


class NoteForm extends StatefulWidget {
  String _title = "";
  Note _note = null;

  NoteForm(String title, [Note note]) {
    this._title = title;
    this._note = note;
  }

  @override
  State<StatefulWidget> createState() {
    return _NoteFormState();
  }
}

class _NoteFormState extends State<NoteForm> {

  double _minimumPadding = 15.0;
  var _priorities = [ 1, 2 ];
  var _titleController = TextEditingController();
  var _descriptionController = TextEditingController();
  var _dateController = TextEditingController();
  DatabaseHelper _databaseHelper = DatabaseHelper();
  var _selectedPriority = 1;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget._title),),
      body: Builder(
        builder: (scaffoldContext) => Form(
          child: Column(
            children: <Widget>[
              Container(
                child: Padding(
                  padding: EdgeInsets.all(_minimumPadding),
                  child: TextFormField(
                    controller: _titleController,
                    decoration: InputDecoration(
                        labelText: "Title",
                        hintText: "Enter title"
                    ),
                  ),
                ),
              ),
              Container(
                  child: Padding(
                    padding: EdgeInsets.all(_minimumPadding),
                    child: TextFormField(
                      controller: _descriptionController,
                      decoration: InputDecoration(
                          labelText: "Description",
                          hintText: "Enter description"
                      ),
                    ),
                  )
              ),
              Container(
                child: Padding(
                  padding: EdgeInsets.all(_minimumPadding),
                  child: TextFormField(
                    controller: _dateController,
                    decoration: InputDecoration(
                        labelText: "Date",
                        hintText: "Enter date"
                    ),
                  ),
                ),
              ),
              Container(
                child: Padding(
                  padding: EdgeInsets.all(_minimumPadding),
                  child: DropdownButton<int>(
                    value: _selectedPriority,
                    items: _priorities.map((dropdownItem) {
                      return DropdownMenuItem<int>(
                        value: dropdownItem,
                        child: Text(dropdownItem == 1? "Low": "High"),
                      );
                    }).toList(),
                    onChanged: (int newSelectedValue) {
                      setState(() {
                        _selectedPriority = newSelectedValue;
                      });
                    },
                  ),
                ),
              ),
              Container(
                child: Padding(
                  padding: EdgeInsets.all(_minimumPadding),
                  child: RaisedButton(
                    child: Text(
                        "Save"
                    ),
                    onPressed: () {
                      _save(scaffoldContext);
                    },
                  ),
                ),
              )
            ],
          ),
        ),
      )
    );
  }

  void _save(BuildContext context) async {
    Note note = Note();
    note.title = _titleController.text;
    note.description = _descriptionController.text;
    note.date = _dateController.text;
    note.priority = _selectedPriority;

    if (widget._note != null && widget._note.id!=null) {
      //update
      _databaseHelper.updateNote(note);
      this.showSnackBar(context, "Note has been updated.");
    } else {
      //create
      _databaseHelper.insertNote(note);
      this.showSnackBar(context, "Note has been added.");
    }

    closeForm(context);
  }

  void showSnackBar(BuildContext context, String message) {
    var snackBar = SnackBar(
      content: Text(message),
      action: SnackBarAction(
        label: "UNDO",
        onPressed: () {

        },
      ),
    );

    Scaffold.of(context).showSnackBar(snackBar);
  }

  void closeForm(BuildContext context) {
    Navigator.pop(context, true);
  }
}

当我运行我的应用程序时,它仅显示空白屏幕,如下所示。

enter image description here

如您所见,我正在使用debugPrint方法注销从数据库返回的记录数。就是说数据库中有6条记录。它只是不显示记录。我的代码有什么问题,我该如何解决?

最佳答案

正如我在评论中提到的那样,由于异步任务而发生的事情需要花费一些时间来执行,如果不保持异步,则setState函数将在实际数据加载或设置之前执行。

因此,进行以下更改可以解决您的问题。

使getNotes async method

getNotes().then((noteresponce){ setState((){ _notes=noteresponce; _count = _notes.length;} });

关于sqlite - 列表项更改时Flutter ListView不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61022155/

相关文章:

ios - 核心数据 sqlite 文件已损坏

android - 如果行 ID 不存在则返回一个字符串

android - 仅 Release模式 APK 构建的 flutter 问题

Dart 可观察列表,不会在更改时删除并重新插入所有元素

dart - Dart 的目标是在编译非 dart 目标方面取代 Haxe 吗?

php - 如何根据日期列中的月份从SQLite获取数据

javascript - Sequelizejs--如何将日期时间写入MSSQL

button - 如何在按钮中使用 if else 条件 - flutter

Flutter 应用程序在 Android 物理设备的任务管理器中显示黑屏

android - 将 Cloud Firestore 和 Firebase 添加到 Flutter 项目 (Android)