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

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

尽管 Flutter 本身不包含任何数据库功能,但可以使用各种第三方库和插件来在 Flutter 应用程序中实现数据库功能;

以下将使用sqflite作为例子,sqflite允许在 Flutter 应用程序中执行 SQL 查询,创建和管理数据库表,以及执行其他常见的数据库操作。

在将sqflite添加到Flutter项目的依赖中后,就可以使用代码创建数据库和表了。

dart 复制代码
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  
    )  
  ''');  
}

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

dart 复制代码
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的地址和端口。

dart 复制代码
  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并对其响应。

dart 复制代码
  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),在事务中执行数据库操作可以确保操作的原子性,即要么全部成功,要么全部失败;

通过使用事务,我们可以实现对数据库操作的加锁,确保同一时间只有一个线程可以访问数据库中的特定资源。

dart 复制代码
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创建锁。

dart 复制代码
import 'package:synchronized/synchronized.dart';

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

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实例。

相关推荐
不羁。。2 分钟前
【撸靶笔记】第七关:GET - Dump into outfile - String
数据库·笔记·oracle
yangchanghua1112 小时前
pgsql 如何查询今天范围内的数据(当天0点0分0秒 - 当天23点59分59秒....)
数据库·pgsql
larance2 小时前
SQLAlchemy 的异步操作来批量保存对象列表
数据库·python
python_chai2 小时前
从数据汇总到高级分析,SQL 查询进阶实战(下篇)—— 分组、子查询与窗口函数全攻略
数据库·sql·mysql
在努力的前端小白2 小时前
Spring Boot 敏感词过滤组件实现:基于DFA算法的高效敏感词检测与替换
java·数据库·spring boot·文本处理·敏感词过滤·dfa算法·组件开发
未来之窗软件服务2 小时前
自建知识库,向量数据库 (九)之 量化前奏分词服务——仙盟创梦IDE
数据库·仙盟创梦ide·东方仙盟·自建ai·ai分词
冒泡的肥皂5 小时前
MVCC初学demo(一
数据库·后端·mysql
.Shu.6 小时前
Redis Reactor 模型详解【基本架构、事件循环机制、结合源码详细追踪读写请求从客户端连接到命令执行的完整流程】
数据库·redis·架构
薛晓刚9 小时前
当MySQL的int不够用了
数据库
江上清风山间明月9 小时前
Flutter AlwaysScrollableScrollPhysics详解
flutter·滚动·scrollable·scrollphysics