Flutter 日记APP-数据库Sqflite

前言

日记App的主要功能是记录文本信息,类似于日常的笔记本,一个笔记本对应的一个梦想日记。考虑到日记信息需要长期存储且不确定日记内容的多少及大小,所以采用Sqflite数据库进行本地缓存。

为了便于操作,将数据库操作封装成单例

java 复制代码
import 'package:sqflite/sqflite.dart';
class SSLDBManager{
  static int version = 1;
  //单例类创建
  SSLDBManager._internal();
  //保存单例
  static final SSLDBManager _dbManager = SSLDBManager._internal();
  //工厂构造函数
  factory SSLDBManager(){
    return _dbManager;
  }
  //数据库
  late final Database db;
}

设计数据格式,创建表格

dart 复制代码
//考虑到数据库要在程序启动时先启动,而数据库的初始化是异步的,这里也采用异步函数,后面通过await函数同步执行
Future<bool> openDB(String path) async{
//获取数据库存放地址
  var databasesPath = await getDatabasesPath();
  String dbPath = '$databasesPath/$path.db';
  //打开数据库,如果数据库中没有对应的表格则创建
  db = await openDatabase(dbPath, version: 1, onCreate: (Database db, int version){
      String dreamTable = "CREATE TABLE If NOT EXISTS Dreams ("
          "id INTEGER PRIMARY KEY autoincrement,"
          "dreamId TEXT,"//唯一笔记本id
          "type INTEGER,"//笔记本类型,便于后面扩展做其他类型笔记
          "title TEXT,"
          "cycleType INTEGER,"//循环闹钟提醒类型,日、周、月
          "isWarning INTEGER,"//是否开启闹钟
          "cycleTime INTEGER,"//循环体系的时间单位,如果是周则对应周几,如果是月对应每月几号
          "time TEXT,"//每天闹钟的提醒时间,比如晚上九点21:00
          "subTitle TEXT,"//日记描述
          "createTime INTEGER,"//创建时间
          "state INTEGER,"//日记状态,是否完结等
          "lastTime INTEGER)";//最后更新时间
      db.execute(dreamTable);

      String recordTable = "CREATE TABLE If NOT EXISTS Records ("
          "id INTEGER PRIMARY KEY autoincrement,"
          "recordId TEXT,"//日记ID
          "type INTEGER,"//日记类型,便于后面扩展
          "dreamId TEXT,"//对应的日记本ID
          "title TEXT,"
          "subTitle TEXT,"
          "time TEXT,"//日记时间
          "price TEXT,"
          "createTime INTEGER,"//创建日记时间
          "lastTime INTEGER,"//最后修改时间
          "filePath TEXT)";//便于扩展其他日记类型
      db.execute(recordTable);

  }, onUpgrade: (Database db, int oldVersion, int version) async {

  });

  return true;
}

数据库操作

dart 复制代码
//TODO: 插入梦想记录
  void insertDream(Map data, SSLDBCallback? callback) async {
    await db.transaction((txn) async{
      String dreamId = data["dreamId"].toString();
      int type = data["type"];
      String title = data["title"].toString();
      String subTitle = data["subTitle"].toString();
      String time = data["time"].toString();
      int cycleType = data["cycleType"];
      int cycleTime = data["cycleTime"];
      int createTime = data["createTime"];
      int lastTime = data["lastTime"];
      bool isWarning = data["isWarning"];
      String dataStr = "INSERT INTO Dreams("
          "dreamId,"
          "type,"
          "title,"
          "cycleType,"
          "cycleTime,"
          "isWarning,"
          "time,"
          "subTitle,"
          "state,"
          "createTime,"
          "lastTime"
          ") VALUES('$dreamId', $type, '$title', $cycleType, $cycleTime, $isWarning, '$time', '$subTitle', 0, $createTime, $lastTime)";
      int id1 = await txn.rawInsert(dataStr);
      if (callback != null){
        callback(id1, "insert dream success");
      }
      debugPrint('ssl get id $id1');
    });
  }
  //TODO: 更新梦想数据
  Future<int> updateDream(Map data) async {
    String dreamId = data["dreamId"].toString();
    String title = data["title"].toString();
    String subTitle = data["subTitle"].toString();
    String time = data["time"].toString();
    int cycleType = data["cycleType"];
    int cycleTime = data["cycleTime"];
    int lastTime = data["lastTime"];
    bool isWarning = data["isWarning"];
    String sqlData = 'UPDATE Dreams SET '
        "title='$title',"
        "subTitle='$subTitle',"
        "time='$time',"
        "cycleType=$cycleType,"
        "cycleTime=$cycleTime,"
        "lastTime=$lastTime,"
        "isWarning=$isWarning "
        "WHERE dreamId='$dreamId'";
    int count = await db.rawUpdate(sqlData);
    return count;
  }
  //TODO: 查询梦想记录
  Future<List<DreamModel>> selectDream() async {
    String data = "SELECT * FROM Dreams";
    List<Map<String, dynamic>> list = await db.rawQuery(data);
    if (list.isEmpty){
      return [];
    }

    List<DreamModel> models = list.map((e) => DreamModel.fromJson(e)).toList();
    return models;
  }

  //TODO: 查询梦想记录
  Future<DreamModel?> selectDreamById(String dreamId) async {
    String data = "SELECT * FROM Dreams WHERE dreamId = '$dreamId'";
    List<Map<String, dynamic>> list = await db.rawQuery(data);
    if (list.isEmpty){
      return null;
    }
    //将查询到的数据映射成模型
    List<DreamModel> models = list.map((e) => DreamModel.fromJson(e)).toList();
    return models.first;
  }


  //TODO: 更新梦想状态
  Future<int> updateDreamState(String dreamId, int state) async {
    String data = 'UPDATE Dreams SET name = state, value = $state WHERE dreamId = $dreamId';
    int count = await db.rawUpdate(data);
    return count;
  }
  //TODO:插入日记记录
  void insertRecord(Map data, SSLDBCallback? callback) async {
    await db.transaction((txn) async{
      String dreamId = data["dreamId"].toString();
      String recordId = data["recordId"].toString();
      int type = data["type"];
      String title = data["title"].toString();
      String subTitle = data["subTitle"].toString();
      String time = data["time"].toString();
      int createTime = data["createTime"];
      String filePath = data["filePath"].toString();
      int lastTime = data["lastTime"];
      String price = data["price"].toString();
      String dataStr = "INSERT INTO Records("
          "dreamId,"
          "recordId,"
          "type,"
          "title,"
          "subTitle,"
          "time,"
          "price,"
          "createTime,"
          "lastTime,"
          "filePath"
          ")VALUES('$dreamId', '$recordId', $type, '$title', '$subTitle', '$time', '$price', $createTime, $lastTime, '$filePath')";
      int id1 = await txn.rawInsert(dataStr);
      debugPrint('ssl get id $id1');
      if (callback != null){
        callback(id1, "insert record success");
      }
    });
  }
  //TODO: 更新日记数据
  Future<int> updateRecord(Map data) async {
    String dreamId = data["dreamId"].toString();
    String recordId = data["recordId"].toString();
    String title = data["title"].toString();
    String subTitle = data["subTitle"].toString();
    String time = data["time"].toString();
    String filePath = data["filePath"].toString();
    int lastTime = data["lastTime"];
    int createTime = data["createTime"];
    String price = data["price"].toString();
    String sqlData = 'UPDATE Records SET '
        "title='$title',"
        "subTitle='$subTitle',"
        "time='$time',"
        "lastTime=$lastTime,"
        "createTime=$createTime,"
        "price='$price',"
        "filePath='$filePath' "
        "WHERE recordId='$recordId' AND dreamId='$dreamId'";
    int count = await db.rawUpdate(sqlData);
    return count;
  }
  //TODO: 查询日记记录
  Future<List<RecordModel>> selectRecord(String dreamId, int page) async {
    int size = 20;//order by id
    String dataStr = "SELECT * FROM Records  WHERE dreamId='$dreamId' ORDER BY lastTime DESC limit $size offset $page";
    List<Map<String, dynamic>> list = await db.rawQuery(dataStr);
    if (list.isEmpty){
      return [];
    }
    //将查询到的数据映射成模型
    List<RecordModel> models = list.map((e) => RecordModel.fromJson(e)).toList();
    return models;
  }

  //TODO: 根据ID查询日记记录
  Future<RecordModel?> selectRecordById(String recordId, String dreamId) async {
    String data = "SELECT * FROM Records WHERE recordId='$recordId' AND dreamId='$dreamId'";
    List<Map<String, dynamic>> list = await db.rawQuery(data);
    if (list.isEmpty){
      return null;
    }

    List<RecordModel> models = list.map((e) => RecordModel.fromJson(e)).toList();
    return models.first;
  }

  //TODO: 查询日记记录条数
  Future<int> selectRecordCount(String  dreamId) async {
    String data = "SELECT COUNT(*) FROM Records WHERE dreamId='$dreamId'";
    int? count = Sqflite.firstIntValue(await db.rawQuery(data));

    return count ?? 0;
  }

}

数据库使用

上面是数据的基本操作的封装,下面介绍一下使用:

dart 复制代码
//初始化数据库
await sslDB.openDB("ssl");

void saveDreamRecordAction() async{
//如果ID不存在则插入数据
  if (recordId.isEmpty){
    Map data = {
      "dreamId" : dreamId,
      "title" : titleStr,
      "price" : "",
      "recordId" : SSLEngine.createRecordId(),
      "time" : timeStr,
      "subTitle" : subDescribe,
      "createTime" : createTime,
      "lastTime" : createTime,
      "type" : 1,
      "filePath" : "",
    };
    //这里是用数据库完成后回调函数
    sslDB.insertRecord(data, (int id, String value){
      debugPrint("ssl create dream $id  $data");
      if (id > 0){
        Fluttertoast.showToast(msg: SSLLocales.l_dreamRecord_add_success.tr);

        Get.back(result: id);
      }else{

      }
    });
  }else{
  //id 存在则更新数据
    int temTimestamp = DateTime.now().millisecondsSinceEpoch;
    Map data = {
      "dreamId" : dreamId,
      "title" : titleStr,
      "price" : "",
      "recordId" : recordId,
      "time" : timeStr,
      "subTitle" : subDescribe,
      "createTime" : createTime,
      "lastTime" : temTimestamp,
      "type" : 1,
      "filePath" : "",
    };
    //等待数据库数据存储完成
    int count = await sslDB.updateRecord(data);
    if (count > 0){
      RecordModel? recordTem = await sslDB.selectRecordById(recordId,dreamId);
      if (recordTem != null){
        Fluttertoast.showToast(msg: SSLLocales.l_toast_record_update.tr);
        Get.back(result: recordTem);
      }
    }
  }
}

项目较简单,大概的操作就这些,后续会继续更新其他开发内容,有不当之处,欢迎指正。

相关推荐
一头小火烧2 小时前
flutter打包签名问题
flutter
sunly_2 小时前
Flutter:异步多线程结合
flutter
AiFlutter2 小时前
Flutter网络通信-封装Dio
flutter
B.-2 小时前
Flutter 应用在真机上调试的流程
android·flutter·ios·xcode·android-studio
有趣的杰克2 小时前
Flutter【04】高性能表单架构设计
android·flutter·dart
iFlyCai12 小时前
Xcode 16 pod init失败的解决方案
ios·xcode·swift
sunly_13 小时前
Flutter:父组件,向子组件传值,子组件向二级页面传值
flutter
爱学习的绿叶17 小时前
flutter TabBarView 动态添加删除页面
flutter
趴菜小玩家19 小时前
使用 Gradle 插件优化 Flutter Android 插件开发中的 Flutter 依赖缺失问题
android·flutter·gradle
郝晨妤21 小时前
HarmonyOS和OpenHarmony区别是什么?鸿蒙和安卓IOS的区别是什么?
android·ios·harmonyos·鸿蒙