SQLite/SQFlite 更新在 Flutter 应用程序中不起作用

SQLite/ SQFlite updating is not working in a Flutter app

我正在使用 Flutter 和 Dart 编程语言构建应用程序。我使用 SQLite 作为本地数据库。现在我正在开发一个功能,当 ListView 的一个项目被点击时,我将数据传递到一个新的表单页面。但是更新数据不起作用。

以下是我的数据库助手class。注意updateNote方法

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> updateNote(Note note) async {
    var db = await this.database;

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

  //there are other methods hidden here
}

我有一个小部件 class,它使用以下代码显示 ListView

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() {
    getNotes();
  }

  @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) {
      getNotes();
    }
  }

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

      setState(() {
        _notes = notes;
        _count = notes.length;
      });
    });
  }
}

如您所见,当单击 ListView 的一个项目时,我将数据传递给下一个小部件 NoteForm。

这是我的 NoteForm class 的实现。

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(this._title, this._note);
  }
}

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;
  String _title;
  Note _note;

  _NoteFormState(String title, [Note note]) {
    this._title = title;
    this._note = note;
    if (this._note != null && this._note.id != null) {
      _titleController.text = this._note.title;
      _descriptionController.text = this._note.description;
      _dateController.text = this._note.date;
      _selectedPriority = this._note.priority;
    }
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(title: Text(this._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);
      debugPrint("Note title is ${note.title}");
      debugPrint("Note description is ${note.description}");
      debugPrint("Note date is ${note.date}");
      debugPrint("Note priority is ${note.priority}");
      debugPrint("Note has been updated.");
      this.showSnackBar(context, "Note has been updated.");
    } else {
      //create
      _databaseHelper.insertNote(note);
      debugPrint("Note has been created.");
      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);
  }
}

当我更新笔记时,它没有更新。列表视图仍然显示相同的数据。我的代码有什么问题,我该如何解决?

当你打电话给 _databaseHelper.updateNote(note); 我相信你应该等待这个所以 await _databaseHelper.updateNote(note); 因为它 return 是未来所以现在你不是在等待你的数据至 return。您还有一些其他功能 return 期货。

也许你需要等待或未来,你在哪里打电话

也在 _databaseHelper.updateNote 中打印 你可以看到哪个先出现

  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
      await _databaseHelper.updateNote(note);
      debugPrint("Note title is ${note.title}");
      debugPrint("Note description is ${note.description}");
      debugPrint("Note date is ${note.date}");
      debugPrint("Note priority is ${note.priority}");
      debugPrint("Note has been updated.");
      this.showSnackBar(context, "Note has been updated.");
    } else {
      //create
      await _databaseHelper.insertNote(note);
      debugPrint("Note has been created.");
      this.showSnackBar(context, "Note has been added.");
    }

    closeForm(context);
  }

我发现了问题。这是我的代码。看看下面的片段。

  Note note = Note();
    note.title = _titleController.text;
    note.description = _descriptionController.text;
    note.date = _dateController.text;
    note.priority = _selectedPriority;

我没有分配 id 值。因此该 id 始终为 null 以进行更新。感谢您的帮助。