Flutter 重启后重新找回已删除的 SQLLite 笔记记录

问题描述 投票:0回答:1

编辑:看来此错误仅发生在“重新启动”时,而不会发生在热重载时。

我面临的问题是,已从 SQLLite 数据库中删除的注释在重新启动后又回来了。我不确定为什么会发生这种情况,例如,我删除了一个注释,然后重新启动应用程序,相同的注释重新出现在屏幕上。这很奇怪,因为之前我使用相同的代码删除了注释,但它们没有回来并且永远消失了。

你知道为什么会发生这种情况吗?似乎注释在删除后仍保留在数据库中,然后一旦检索到数据库,它们就会返回,但我检查了并且每次都会调用await database.delete()。

import 'package:flutter/material.dart';
import 'package:notepad/screens/Note.dart';
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

//Singleton
class DatabaseProvider {
  static Database? _database;
  static bool _isDatabaseInitialized = false;

  static Future<Database> get database async {
    if (_isDatabaseInitialized) {
      return _database!;
    }
    _database = await _initDatabase();
    _isDatabaseInitialized = true;
    return _database!;
  }

  static Future<Database> _initDatabase() async {
    // Set the path to the database. Note: Using the `join` function from the
    // `path` package is best practice to ensure the path is correctly
    // constructed for each platform.
    final path = join(await getDatabasesPath(), 'notes.db');
    return await openDatabase(
      path,
      // When the database is first created, create a table to store notes.
      onCreate: (db, version) {
        // Run the CREATE TABLE statement on the database.
        return db.execute(
          'CREATE TABLE Notes(id INTEGER PRIMARY KEY, title TEXT, subtitle TEXT)',
        );
      },
      // Set the version. This executes the onCreate function and provides a
      // path to perform database upgrades and downgrades.
      version: 1,
    );
  }
}

class ListOfNotes extends StatefulWidget {
  const ListOfNotes({super.key});

  @override
  State<ListOfNotes> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<ListOfNotes> {
  bool _isInitialized = false;

  var noteTitle = [];
  var noteContent = [];

  late var originalNoteTitle = [];
  late var originalNoteContent = [];

  late var isSelected =
      List<bool>.filled(noteTitle.length, false, growable: true);
  late var tileColor =
      List<Color>.filled(noteTitle.length, Colors.white, growable: true);

  var appBarActionsEnabled = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
          itemCount: noteTitle.length,
          prototypeItem: ListTile(
            contentPadding: EdgeInsets.all(10),
            title:
                Text(noteTitle.firstWhere((element) => true, orElse: () => '')),
            subtitle: Text(
                noteContent.firstWhere((element) => true, orElse: () => '')),
          ),
          itemBuilder: (context, index) {
            return ListTile(
                title: Text(noteTitle[index]),
                subtitle: Text(noteContent[index]),
                onLongPress: () {
                  toggleSelection(index);
                  toggleActions();
                },
                onTap: () {
                  _editNote(context, index);
                },
                selected: isSelected[index],
                tileColor: tileColor[index],
                enabled: true);
          }),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          _navigateAndDisplaySelection(context);
        },
      ),
    );
  }

  Future<void> deleteSelectedNotes() async {
    final database = await DatabaseProvider.database;
    // Remove the Note from the database.
    for (int i = 0; i < noteTitle.length; i++) {
      if (isSelected[i] == true) {
        await database.delete(
          'Notes',
          // Use a `where` clause to delete a specific note.
          where: 'id = ?',
          // Pass the Note's id as a whereArg to prevent SQL injection.
          whereArgs: [i],
        );
      }
    }
    setState(() {
      for (int i = 0; i < isSelected.length; i++) {
        if (isSelected[i] == true) {
          noteTitle.removeAt(i);
          noteContent.removeAt(i);
          originalNoteTitle.removeAt(i);
          originalNoteContent.removeAt(i);
          isSelected.removeAt(i);
          tileColor.removeAt(i);
        }
      }
    });
  }
@override
  void initState() {
    super.initState();
    _initializeNotes();
  }

  Future<void> _initializeNotes() async {
    if (!_isInitialized) {
      await _retrieveNotes();
      _isInitialized = true;
    }
  }

  Future<void> _retrieveNotes() async {
    var tempNoteTitleWait = [];
    var tempNoteContentWait = [];

    final database = await DatabaseProvider.database;

    final List<Map<String, dynamic>> result = await selectNotesDB(database);

    for (final row in result) {
      tempNoteTitleWait.add(row['title']);
      tempNoteContentWait.add(row['subtitle']);
    }

    setState(() {
      noteTitle = List<String>.from(tempNoteTitleWait);
      noteContent = List<String>.from(tempNoteContentWait);
      originalNoteTitle = List<String>.from(tempNoteTitleWait);
      originalNoteContent = List<String>.from(tempNoteContentWait);
    });
  }
flutter sqlite
1个回答
0
投票

事实证明,数据库和我正在使用的列表上一定有一些不同的索引,因此作为一半措施,我使用了 title[index] 代替,它似乎有效,我不确定为什么它不删除两个这样做时具有相同标题的注释,但它按预期工作,所以我猜这将是托德·霍华德“它就是有效”的一个实例。

Future deleteSelectedNotes() 异步 { 最终数据库=等待DatabaseProvider.database;

List<int> indicesToDelete = [];
// Remove the Note from the database.
for (int i = 0; i < isSelected.length; i++) {
  if (isSelected[i] == true) {
    await database.delete(
      'Notes',
      // Use a `where` clause to delete a specific note.
      where: 'title = ?',
      // Pass the Note's id as a whereArg to prevent SQL injection
      whereArgs: [noteTitle[i]],
    );

    indicesToDelete.add(i);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.