不将 flutter 开关值保存到 sqflite 数据库

Not saving the flutter switch value to sqflite database

我完全是 sqliteflutter 的初学者。我试图为我的 flutter to do 应用程序创建一个本地 database。所以我看了一些 youtube 视频并开始使用 flutter sqflite 插件实现数据库。一切正常,因为我所做的只是复制输入你的块茎代码,直到我不得不向代码添加一个额外的布尔参数,以便跟踪任务的状态(比如是否完成任务)。我使用 int 值来保存 bool,而 sqlite 不支持 boolean 值。我使用了两个 functions,一个更新 text,另一个更新 switch 值。

其次,当我点击一个开关时,它会触发 list 中的所有开关。我也想解决这个问题。

任务的模型class

class Tasksdb {
  final int? id;
  final String taskName;
  bool isDone;

  Tasksdb({
    this.id,
    required this.taskName,
    required this.isDone,
  });

  factory Tasksdb.fromMap(Map<String, dynamic> json) => Tasksdb(
      id: json['id'],
      taskName: json['taskName'],
      isDone: (json['isDone'] as int) == 0 ? false : true);

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'taskName': taskName,
      'isDone': isDone,
    };
  }
}  

数据库助手class

 class DatabaseHelper {
  DatabaseHelper._privateConstructor();
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();

  static Database? _database;
  Future<Database> get database async => _database ??= await _initDatabase();

  Future<Database> _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, 'tasks.db');
    return await openDatabase(
      path,
      version: 1,
      onCreate: _onCreate,
    );
  }

  Future _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS "taskstable" (
    "id"    INTEGER,
    "taskName"  TEXT,
    "isDone"    INTEGER NOT NULL DEFAULT 0,
    PRIMARY KEY("id" AUTOINCREMENT)
);
      ''');
  }

  Future<List<Tasksdb>> getTasks() async {
    Database db = await instance.database;
    var tasksQuery = await db.query(
      'taskstable',
    );
    List<Tasksdb> taskList = tasksQuery.isNotEmpty
        ? tasksQuery.map((c) => Tasksdb.fromMap(c)).toList()
        : [];
    return taskList;
  }

  Future<int> add(Tasksdb task) async {
    Database db = await instance.database;
    return await db.insert('taskstable', {
      'id': task.id,
      'taskName': task.taskName,
      'isDone': 0,
    });
  }


  Future<int> update(Tasksdb task) async {
    Database db = await instance.database;
    return await db.update(
      'taskstable',
      task.toMap(),
      where: "id = ?",
      whereArgs: [task.id],
    );
  }

  Future<int> updateIsDone(bool isDoneTodb) async {
    Database db = await instance.database;
    return await db.update(
      'taskstable',
      {
        'isDone': isDoneTodb == true ? 1 : 0,
      },
    );
  }
}

主屏幕小部件

class SqliteApp extends StatefulWidget {
  const SqliteApp({Key? key}) : super(key: key);

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

class _SqliteAppState extends State<SqliteApp> {
  int? selectedId;
  final textController = TextEditingController();
  bool isDone = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: TextField(
            controller: textController,
          ),
        ),
        body: Center(
          child: FutureBuilder<List<Tasksdb>>(
              future: DatabaseHelper.instance.getTasks(),
              builder: (BuildContext context,
                  AsyncSnapshot<List<Tasksdb>> snapshot) {
                if (!snapshot.hasData) {
                  return const Center(child: Text('Loading...'));
                }
                return snapshot.data!.isEmpty
                    ? const Center(child: Text('No tasks in List.'))
                    : ListView(
                        children: snapshot.data!.map((task) {
                          return Center(
                            child: Card(
                              color: selectedId == task.id
                                  ? Colors.green
                                  : Colors.yellow,
                              child: ListTile(
                                trailing: Switch(   //the problem is here, doesn't save to db
                                    value: isDone,
                                    onChanged: (val) async {
                                      setState(() {
                                        isDone = val;
                                      });
                                      await DatabaseHelper.instance
                                          .updateIsDone(
                                        isDone,
                                      );
                                    }),
                                title: Text(task.taskName),
                                onTap: () {
                                  setState(() {
                                    if (selectedId == null) {
                                      textController.text = task.taskName;
                                      selectedId = task.id;
                                    } else {
                                      textController.text = 'add something';
                                      selectedId = null;
                                    }
                                  });
                                },
                              ),
                            ),
                          );
                        }).toList(),
                      );
              }),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () async {
            await DatabaseHelper.instance.add(
              Tasksdb(
                taskName: textController.text,
                isDone: false,
              ),
            );
            setState(() {
              textController.clear();
              selectedId = null;
            });
          },
        ),
      ),
    );
  }
}

我找到了答案:(如果有人有同样的问题) 我从 material 应用程序小部件中删除了 bool isDone,而不是将开关 val 分配给 bool,而是将其分配给数据库的 task.isDone 值。为了避免 switch 的自动触发,我将 Taskdb 解析为 updateIsDone function

Future<int> updateIsDone(Tasksdb task, bool isDoneTodb) async {
    Database db = await instance.database;
    return await db.update(
        'taskstable',
        {
          'isDone': isDoneTodb == true ? 1 : 0,
        },
        where: "id = ?",
        whereArgs: [task.id]);
  }

...

Switch(
     value: task.isDone,
     onChanged: (val) async {
            setState(() {
                 task.isDone = val;
            });
     await DatabaseHelper.instance
     .updateIsDone(task, task.isDone);
       });