Flutter开发进阶之并发操作数据库

Flutter开发进阶之并发操作数据库

尽管 Flutter 本身不包含任何数据库功能,但可以使用各种第三方库和插件来在 Flutter 应用程序中实现数据库功能;
以下将使用sqflite作为例子,sqflite允许在 Flutter 应用程序中执行 SQL 查询,创建和管理数据库表,以及执行其他常见的数据库操作。
Flutter开发
在将sqflite添加到Flutter项目的依赖中后,就可以使用代码创建数据库和表了。

import 'package:sqflite/sqflite.dart';  
  
Future<Database> getDatabase() async {  
  final dir = (await getDatabasesPath()).resolve('my_database.db');  
  return await openDatabase(dir.path, version: 1, onCreate: _onCreate);  
}  
  
Future _onCreate(Database db, int version) async {  
  await db.execute('''  
    CREATE TABLE user (  
      id INTEGER PRIMARY KEY AUTOINCREMENT,  
      name TEXT,  
      age INTEGER  
    )  
  ''');  
}

然后我们可以做一些插入、查询、更新和删除数据库中数据的操作。

import 'package:sqflite/sqflite.dart';  
  
Future<void> insertData() async {  
  final db = await getDatabase();  
  await db.execute(  
    'INSERT INTO user (name, age) VALUES (?, ?)',  
    ['John', 25],  
  );  
}  
  
Future<List<Map<String, dynamic>>> queryData() async {  
  final db = await getDatabase();  
  return await db.query('user');  
}  
  
Future<int> updateData() async {  
  final db = await getDatabase();  
  return await db.update(  
    'user',  
    {'age': 26},  
    where: 'name = ?',  
    whereArgs: ['John'],  
  );  
}  
  
Future<int> deleteData() async {  
  final db = await getDatabase();  
  return await db.delete('user', where: 'name = ?', whereArgs: ['John']);  
}

在实际应用中并不会这么简单,特别是当我们有需求在多个位置去操作数据库的时候,这时候可能会有线程安全的问题;
比如说在一个作用域内,有多台设备需要在我所在的这台设备操作数据库;
首先我所在的设备作为主机要监听子机的UDP广播,然后将通过我验证的子机向其发送我开放的TCP的地址和端口。

  const String multicastGroup = '224.0.0.1'; // 定义多播组地址  
  const int port = 5000; // 定义端口号  
  const int bufferSize = 1024; // 定义缓冲区大小  
  final ByteData buffer = ByteData(bufferSize);  
  DatagramSocket socket = DatagramSocket();  
  socket.bind(port);  
  socket.joinMulticastGroup(multicastGroupIP);  
  socket.listen(buffer.length);  
  socket.onDatagramReceived = (Datagram datagram) async {  
    final String receivedData = datagram.data.toString();  
    // 处理接收到的数据...  
  };  

然后合法的子机会收到我的信息,就可以通过TCP向主机发送命令;
这时就需要主机时刻监听TCP并对其响应。

  const int port = 5000; // 定义端口号  
  final ServerSocket serverSocket = ServerSocket(port);  
  serverSocket.onAccept = (ServerSocket socket) async {  
    final Stream stream = socket.accept();  
    stream.transform(utf8.decoder).listen((String data) {  
      // 处理接收到的数据...  
    });  
  };  

假设对其响应的本身是对数据库进行操作,而主机内部也同时对数据库有了操作,这时候就要注意数据库的线程安全了;
首先可以通过对数据库的操作加锁来保证,比如sqflite提供了事务(Transaction),在事务中执行数据库操作可以确保操作的原子性,即要么全部成功,要么全部失败;
通过使用事务,我们可以实现对数据库操作的加锁,确保同一时间只有一个线程可以访问数据库中的特定资源。

Future<void> insertData() async {  
  final db = await getDatabase();  
  await db.transaction((txn) async {  
    // 在事务中执行数据库操作  
    await txn.execute('INSERT INTO user (name, age) VALUES (?, ?)', ('John', 25));  
    // 提交事务  
    await txn.commit();  
  });  
}  

或者直接使用synchronized创建锁。

import 'package:synchronized/synchronized.dart';

还可以通过数据库连接池来限制最大连接数量。

import 'package:sqflite/sqflite.dart';  
  
class DatabaseHelper {  
  static final DatabaseHelper _instance = DatabaseHelper._internal();  
  static Database? _db;  
  
  factory DatabaseHelper() {  
    return _instance;  
  }  
  
  Future<Database> get db async {  
    if (_db != null) return _db;  
    _db = await _openDatabase();  
    return _db;  
  }  
  
  Future<void> close() async {  
    if (_db != null) {  
      await _db!.close();  
      _db = null;  
    }  
  }  
  
  Future<Database> _openDatabase() async {  
    final pool = await SqliteConnectionPool.forDatabase('path/to/database.db');  
    pool.maxSize = 10; // 设置最大连接数为10  
    return pool.openDatabase();  
  }  
}

这样同时还避免了直接使用Database实例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/320368.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(Java企业 / 公司项目)分布式事务Seata详解(含Seata+Nacos组合使用)(二)

一. Seata Server配置Nacos 什么是配置中心?配置中心可以说是一个"大货仓",内部放置着各种配置文件,你可以通过自己所需进行获取配置加载到对应的客户端.比如Seata Client端(TM,RM),Seata Server(TC),会去读取全局事务开关,事务会话存储模式等信息.Seata的配置中心…

ElasticSearch _update_by_query

根据查询条件进行数据更新 UPDATE job_call SET admin_id 0 WHERE admin_id 283; kibana.png 1.其中红色框的位置为query的内容&#xff0c;对应为SQL语句中的WHERE admin_id 283 2.划红色线的位置为修改内容&#xff0c;对应SQL中的SET admin_id 0。如果是更新多个字段s…

【2023 我的编程之旅】

前言 转眼 2024 年都过去 14 天了。回顾 2023 有太多技术上的思考以及人生的感悟&#xff0c;接下来趁着 CSDN 官方活动&#xff0c;顺便记录下来。 技术的价值 与现在的年轻人一心只想搞钱不同&#xff0c;刚毕业的时候&#xff0c;我的梦想是进入一家有实力的科技企业&…

Codeforces Bye 2023! - D - Mathematical Problem - 题解

目录 Mathematical Problem 题目大意&#xff1a; 思路解析&#xff1a; 代码实现&#xff1a; Mathematical Problem 题目大意&#xff1a; 第 31 中学的数学家们接到了以下任务&#xff1a; 给你一个多数 n &#xff0c;你需要找出 n 个不同的数&#xff0c;它们都是整…

Linux 内核学习 3 - 虚拟内存和物理内存

虚拟内存其实是 CPU 和操作系统使用的一个障眼法&#xff0c;联手给进程编织了一个假象&#xff0c;让进程误以为自己独占了全部的内存空间&#xff1a; 在 32 位系统中&#xff0c;进程以为自己独占了 3G 的内存空间。 在 64 位系统中&#xff0c;进程以为自己独占了 128T 的…

【MySQL】数据处理之增删改

文章目录 一、增加&#xff08;插入&#xff09;INSERT INTO...VALUES(...,...)VALUES的方式添加情况一&#xff1a;为表的所有字段按默认顺序插入数据情况二&#xff1a;为表的指定字段插入数据情况三&#xff1a;同时插入多条记录 将查询结果插入到表中 二、修改&#xff08;…

开源知识库zyplayer-doc部署指南

1.前置条件 docker已经安装 mysql已经安装且数据库zyplayer-doc存在 服务器ip:192.168.168.99/ 数据库账户:root,密码:123456 2.拉取镜像 docker pull zyplayer/zyplayer-doc:latest 3.启动 docker run -d \--restart unless-stopped \--name zyplayer-doc \-p 8083:8083 …

C语言常用库函数

1.C语言标准库函数 C语言标准库函数由15个头文件组成。 1.数学函数 数学计算是计算机最擅长的运算&#xff0c;计算机大部分运算方法都是基于数学计算执行的。C语言提供了很多用于数学计算的库函数&#xff0c;合理利用这些库函数&#xff0c;将对程序的编写和运行起到事半功…

Python相对导入和绝对导入

目录结构&#xff1a; 在 en_de_model_CDDD.py 文件有两种导入方式可以导入utils.py&#xff0c;分别是 相对导入&#xff1a; from ...public_utils.utils import canonicalize_smiles 绝对导入&#xff1a; from public_utils.utils import canonicalize_smiles 这里推荐使…

大量的视频如何批量随机分割的方法:批量剪辑不求人

在处理大量视频文件时&#xff0c;经常要进行随机分割&#xff0c;满足不同的需求。制作短视频、片段集锦等&#xff0c;批量随机分割视频都是一个高效的方法。下面来看云炫AI智剪如何操作的吧。 分割后的视频缩略图展示&#xff0c;被分割的视频自动分类保存在对应的文件夹中。…

软件测试|Pydantic BaseModel使用详解

简介 当我们在Python中编写应用程序时&#xff0c;通常需要处理和验证数据。Pydantic 是一个流行的库&#xff0c;它可以帮助我们定义数据模型并自动进行数据验证。在Pydantic中&#xff0c;BaseModel是一个核心概念&#xff0c;它用于定义数据模型和验证输入数据。在这篇文章…

第六站:C++面向对象关键字解释说明

this指针: 是一个特殊的指针,放回这个对象本身,this指针是属于实例对象,不能访问静态方法(不属于某一个实例对象,属于共有的,大众的,由类直接调用) 第一种用法: void Human::setName(string name1) {this->name name1; } void Human::setAge(int age1) {this->age a…

拯救者y9000p安装linux、windows双系统。

首先需要准备启动盘 我用的是Win32DiskImager来做的。资源使用的是ubuntu-20.04.6-desktop-amd64.iso。别用低版本&#xff0c;失败很多次之后的教训。 磁盘管理-磁盘分区-右键-压缩卷 这边分区出来之后&#xff0c;不要分配。安装时候会自动分配的。 重启之后F2进去BIOS设置…

张载为往圣继绝学,唯一的错是不够强大

“自古雄才多磨难&#xff0c;从来纨绔少伟男。” 张载&#xff0c;人称“横渠先生”。他在横渠镇&#xff0c;授徒讲学&#xff0c;恢复古礼&#xff0c;试验井田&#xff0c;写书《正蒙》。张载讲学关中&#xff0c;弟子多为关中人&#xff0c;其学派被称作关学。 张载自学…

git-生成证书、公钥、私钥、error setting certificate verify locations解决方法

解决方法 方法1-配置证书、公钥、私钥打开Git Bash设置名称和邮箱执行&#xff0c;~/.ssh执行&#xff0c;ssh-keygen -t rsa -C "这是你的邮箱"&#xff0c;如图&#xff1a;进入文件夹可以看到用记事本之类的软件打开id_rsa.pub文件&#xff0c;并且复制全部内容。…

Python自动化测试框架【生成测试报告】

如何才能让用例自动运行完之后&#xff0c;生成一张直观可看易懂的测试报告呢&#xff1f; 小编使用的是unittest的一个扩展HTMLTestRunner 环境准备 使用之前&#xff0c;我们需要下载HTMLTestRunner.py文件 点击HTMLTestRunner后进入的是一个写满代码的网页&#xff0c;小…

并发编程之并发容器

目录 并发容器 CopyOnWriteArrayList 应用场景 常用方法 读多写少场景使用CopyOnWriteArrayList举例 CopyOnWriteArrayList原理 CopyOnWriteArrayList 的缺陷 扩展迭代器fail-fast与fail-safe机制 ConcurrentHashMap 应用场景 常用方法 并发场景下线程安全举例 Con…

软件测试|教你使用Python下载图片

前言 我一直觉得Windows系统默认的桌面背景不好看&#xff0c;但是自己又没有好的资源可以进行替换&#xff0c;突然我一个朋友提醒了我&#xff0c;网络上的图片这么多&#xff0c;你甚至可以每天换很多个好看的背景&#xff0c;但是如果让我手动去设置的话&#xff0c;我觉得…

编程高手必备:Python字典操作与示例全解析

编程高手必备&#xff1a;Python字典操作与示例全解析 引言Python字典基础字典操作技巧代码示例实际应用案例实际应用案例结语 引言 在编程世界中&#xff0c;高效地处理和组织数据是每位程序员必备的技能。Python&#xff0c;作为一种广受欢迎的编程语言&#xff0c;不仅因其…

mysql原理--undo日志1

1.事务回滚的需求 我们说过 事务 需要保证 原子性 &#xff0c;也就是事务中的操作要么全部完成&#xff0c;要么什么也不做。但是偏偏有时候事务执行到一半会出现一些情况&#xff0c;比如&#xff1a; (1). 事务执行过程中可能遇到各种错误&#xff0c;比如服务器本身的错误&…