在Flutter开发过程中,我门有时候需要对一些数据进行本地的持久化存储,使用sp文件形式虽然也能解决问题,但是有时数据量较大的时候,显然我们文件形式就不太合适了,这时候我们就需要使用数据库进行存储,我们知道在原生中有系统提供的轻量级sqlite数据库,在Flutter强大的生态环境中,也有这样一个数据库插件sqflite: ^2.0.2可以同时在Androud、iOS中进行数据库操作。

1、 创建数据库:这里我以存储我的搜索历史记录为例

首先导入:

import 'package:sqflite/sqflite.dart';

这里我创建了一个数据库帮助类,为了以后数据库更新、升级等作准备:

代码实现:主要是对Database这个类的获取进行了封装。

/// 数据库帮助类
class DbHelper {

  final String path = "laoli.db"; // 数据库名称 一般不变
 //数据库中的表名字 这里是我存错历史搜索记录的表
  static final searchTab = "SearchHistory";
   //私有构造
  DbHelper._();
  static DbHelper? _instance;
  static DbHelper get instance => _getInstance();
  factory DbHelper() {
    return instance;
  }
  static DbHelper _getInstance() {
    if (_instance == null) {
      _instance = DbHelper._();
    }
    return _instance ?? DbHelper._();
  }

/// 数据库默认存储的路径
  /// SQLite 数据库是文件系统中由路径标识的文件。如果是relative,
  /// 这个路径是相对于 获取的路径getDatabasesPath(),
  /// Android默认的数据库目录,
  /// iOS/MacOS的documents目录。

  Future<Database>? _db;

  Future<Database>? getDb() {
    _db ??= _initDb();
    return _db;
  }

  // Guaranteed to be called only once.保证只调用一次
  Future<Database> _initDb() async {
  // 这里是我们真正创建数据库的地方 vserion代表数据库的版本,如果版本改变
  //,则db会调用onUpgrade方法进行更新操作
    final db =
        await openDatabase(this.path, version: 1, onCreate: (db, version) {
      // 数据库创建完成
      // 创建表 一个自增id 一个text
db.execute("create table $searchTab (id integer primary key autoincrement, name text not null)");      
    }, onUpgrade: (db, oldV, newV) {
      // 升级数据库调用 
    ///  db 数据库
   ///   oldV 旧版本号
   //   newV 新版本号
   //   升级完成就不会在调用这个方法了
    });

return db;
  }

// 关闭数据库
  close() async {
    await _db?.then((value) => value.close());
  }
}

java后台开发过程中,数据库肯定都会分层设计,这样的好处可以在使用的过程中极大的提高代码的健壮性以及降低后期的维护成本,在移动前端虽然我们用数据库的地方跟后台相比少之又少,但是我还是建议也对数据库进行分层处理操作,虽然不分层也能实现,但是这样也可以降低我们的对于代码的维护成本以及良好的编程习惯。废话不多说,接下来我们需要创建处理数据的dao层。

这里sqflite封装了一些常用的sql语法,比如增删改查,我们就不需要自己去写sql语法了,这里我简答封装了下增删改查的方法。

具体代码:

/// 数据操作类
class DbSearchHistoryDao {
  /// 增
  static insert(String text) {
    // 去重
    queryAll().then((value) {
      bool isAdd = true;
      for (var data in value) {
        if (data.name == text) {
          isAdd = false;
          break;
        }
      }
      if (isAdd) {
        DbHelper.instance.getDb()?.then((value) => value.insert(
              DbHelper.searchTab,
              DbSearchHotBean(name: text).toJson(),
            ));
      }
    });
  }

  /// 删 全部
  static deleteAll() {
    DbHelper.instance.getDb()?.then((value) => value.delete(
          DbHelper.searchTab,
        ));
  }

  /// 更新数据 通过id更新表内具体行的数据
  static update(DbSearchHotBean dbSearchHotBean) {
    DbHelper.instance.getDb()?.then((value) => value.update(
      DbHelper.searchTab,
      dbSearchHotBean.toJson(),//具体更新的数据
      where: "id = ?"//通过id查找需要更新的数据
      ,whereArgs: [dbSearchHotBean.id]
    ));
  }

  /// 通过name查具体的实体类
  static Future<DbSearchHotBean?> getBean(String name) async {
  var db = await DbHelper.instance.getDb();
  var maps = await db?.query(DbHelper.searchTab,
    columns: ['id','name'],// 获取实体类的哪些字段 默认全部
    where: 'name = ?',//通过实体类中的name字段
    whereArgs: [name]);//具体name的值 限定数据
  if(maps!=null && maps.length > 0) {
       return DbSearchHotBean.fromJson(maps.first);
  }
  return null;
  }

  /// 查 全部all
  static Future<List<DbSearchHotBean>> queryAll() async {
    List<DbSearchHotBean> list = [];
    await DbHelper.instance
        .getDb()
        ?.then((db) => db.query(DbHelper.searchTab).then((value) {
              for (var data in value) {
                list.add(DbSearchHotBean.fromJson(data));
              }
            }));
    return list;
  }
}

实体类:虽然只有一个字段,但是创建实体类方便以后扩展。

class DbSearchHotBean {
  int? id;
  String? name; // 搜索词

  DbSearchHotBean({this.id,required this.name});

  DbSearchHotBean.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
  }

  Map<String, String?> toJson() {
    var map = <String, String?>{};
    map['id'] = id?.toString() ;
    map['name'] = name ?? "";

    return map;
  }
}

具体用法就非常简单了

增:DbSearchHistoryDao.insert(”搜索词“);

删全部:DbSearchHistoryDao.deleteAll();

改:例如将水改为火, 找到水的实体通过自增id修改name

DbSearchHistoryDao.getBean("水").then((value){
  if(value!=null){
    DbSearchHistoryDao.update(DbSearchHotBean(id: value.id,name: "火"));
  }
});

查全部:await DbSearchHistoryDao.queryAll();

到这里数据库的基本用法就介绍完了,当然部分操作比如删指定数据,批量修改、批量删除等操作可以用 到批处理操作,这里就不过多介绍了,有需要的可以查看作者文档。链接

batch = db.batch();
batch.insert('Test', {'name': 'item'});
batch.update('Test', {'name': 'new_item'}, where: 'name = ?', whereArgs: ['item']);
batch.delete('Test', where: 'name = ?', whereArgs: ['item']);
results = await batch.commit();

总结

数据库操作总体上没什么难度,但是当我们数据量比较多的时候,数据表结构的设计就有一定的技术含量了,还有就是我们对于一些sql语句的掌握,因为此插件帮我们封装了常用的功能,如果有比较特殊的需求,还是需要我们掌握一定的sql语法才行,这里就简单的介绍一些常用的方法,在移动前端估计也基本够用了~

到此这篇关于Flutter中数据库的使用教程详解的文章就介绍到这了,更多相关Flutter数据库内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Flutter中数据库的使用教程详解的更多相关文章

  1. 详解前端HTML5几种存储方式的总结

    本篇文章主要介绍了前端HTML5几种存储方式的总结 ,主要包括本地存储localstorage,本地存储sessionstorage,离线缓存(application cache),Web SQL,IndexedDB。有兴趣的可以了解一下。

  2. PhoneGap / iOS上的SQLite数据库 – 超过5mb可能

    我误解了什么吗?Phonegap中的sqlitedbs真的有5mb的限制吗?我正在使用Phonegap1.2和iOS5.解决方法您可以使用带有phonegap插件的原生sqliteDB,您将没有任何限制.在iOS5.1中,Websql被认为是可以随时删除的临时数据…

  3. ios – 领域:如何获取数据库的当前大小

    是否有RealmAPI方法使用RealmSwift作为数据存储来获取我的RealmSwift应用程序的当前数据库大小?

  4. ios – Realm – 无法使用现有主键值创建对象

    我有一个对象有许多狗的人.应用程序有单独的页面,它只显示狗和其他页面显示人的狗我的模型如下我有人存储在Realm中.人有详细页面,我们取,并显示他的狗.如果狗已经存在,我会更新该狗的最新信息并将其添加到人的狗列表中,否则创建新狗,保存并将其添加到人员列表中.这适用于coredata.在尝试用他的狗更新人时,领域会抛出异常无法使用现有主键值创建对象解决方法这里的问题是,即使你正在创建一个全新的Rea

  5. ios – UIWebView中的WebSQL / SQLite数据库的最大大小(phonegap)

    我知道一般来说,Web应用程序的本地存储空间有5MB的限制.本地网页浏览应用程式是否也有这个限制?

  6. ios – Firebase离线存储高级 – 手动同步和进度信息

    >我可以提供一个捆绑数据库–安装App后我可以已经离线查询了Firebase数据?然后我有另一个关于Firebase的主要问题:>JSON存储是伟大的–但是这样我们不关心一个独特的结构,我们必须注意这一点插入总是正确的数据集?我从来没有试图显示实际的进展,但是当您从firebase中检索数据时,始终会在成功检索数据时调用onDataChange方法.https://firebase.google.com/docs/database/android/retrieve-data#read_data_onceC

  7. ios – 如何处理多用户数据库

    我的应用程序就像很多应用程序–它有一个用户输入用户名和密码的登录屏幕,以及登录按钮我的应用程序还使用CoreData来保存大多数用户的业务对象,当然也是用户特定的.我也有一个登出按钮来启用切换用户.这不会发生很多,但仍然是必要的).现在如果不同的用户登录,我需要获取他的具体数据.但是我该如何做呢?

  8. ios – Swift从Firebase数据库中获取特定价值

    我正在尝试从Firebase数据库中获取特定值.我看了一些像谷歌这样的文件,但我做不到.这是数据库的JSON文件:SWIFT代码:我想获得用户的电子邮件价值,而不是每个人.我怎样才能做到这一点?解决方法在您的代码中,快照将包含子值的字典.要访问它们,请将snapshot.value转换为Dictionary,然后访问各个子项是一个快照

  9. ios – Realm Swift:在卸载应用程序后是否可以保留数据库?

    使用realmswift,即使从设备上卸载应用程序,是否可以在设备内存中保留和维护应用程序的领域数据库文件?非常感谢您的帮助.解决方法删除应用程序时,应用程序的所有文件都是剩余的.iOS应用程序是沙盒.这意味着每个应用程序在磁盘中都有自己的空间,并有自己的目录,这些目录充当应用程序及其数据的主页.从iPhone删除应用程序会删除此沙箱,删除与该应用程序关联的所有数据.

  10. ios – 在没有XML的情况下更新sqlite数据库

    我的应用程序需要来自sqlite数据库的数据.它将附带此数据库的一个版本,但我需要定期更新它(很可能每月一次).通常情况下,我一直在通过我设置的一堆网络服务将我的应用程序的其他部分的更新作为XML发送,但我现在正在处理的这个特定数据库非常大(大约20-30MB),而且我当我尝试以这种方式发送时出现超时错误.我尝试将数据库放在我的公司服务器上,然后将其下载到NSData对象中.然后我将该数据对象保存

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部