不保存颤音开关值为SQFLITE数据库

发布于 2025-01-27 04:30:43 字数 6313 浏览 6 评论 0原文

我完全是sqliteflutter的初学者。我试图为我的flutter创建本地数据库进行应用。因此,我观看了一些YouTube视频,并开始使用Flutter sqflite插件来实现数据库。一切都很好,因为我所做的只是复制键入You Tubers代码,直到我必须在布尔值的代码中添加额外的参数,以跟踪任务的状态(例如完成任务是否完成)。我使用int值来保存bool,而sqlite不支持boolean值。我使用了两个函数,一个用于更新文本,另一个用于更新Switch> Switch值。

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

部件的模型类

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

任务数据库Helper类

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

HOMESCREEN小

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

I am a completely a beginner to sqlite and flutter. I was trying to create a local database to my flutter to do app. So I watched some youtube videos and started to implementing a database using flutter sqflite plugin. Everything worked fine because all I did was copy typing the you tubers code, until I had to add an extra parameter to the code which is a boolean, in order to track the status of the task (like done the task or not). I used an int value to save the bool, while sqlite does not supports boolean values. I used two functions, one to update the text and the other to update the switch value.

And secondly when I tap on a switch it triggers all the switches in the list. I want to solve that issue as well.

gif

Model class for the Task

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

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

HomeScreen widget

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧情勿念 2025-02-03 04:30:43

我找到了答案:(如果有人有同样的问题)
我从材料应用程序小部件中删除了bool isdone,而不是将Switch val分配给该bool我将其分配给数据库的task.isdone值。为避免Switch的自动触发器,我将taskdb解析到updateisdone 函数

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

I found the answer: (in case of if someone had the same question)
I removed the bool isDone from the material app widget, and instead of assigning the switch val to that bool I assigned it to database's task.isDone value. To avoid switch's auto trigger, I parsed the Taskdb to the 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);
       }); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文