Flutter数据库管理插件drift_libsql的使用
Flutter数据库管理插件drift_libsql的使用
简介
drift_libsql
是一个用于Flutter应用程序的Turso/Libsql数据库客户端,基于Drift库。它允许你在Flutter应用中轻松地管理和操作Libsql数据库。本文将详细介绍如何在Flutter项目中使用 drift_libsql
插件,并提供一个完整的示例demo。
准备工作
-
添加依赖
在你的pubspec.yaml
文件中添加drift_libsql
依赖:dependencies: drift_libsql: ^最新版本
-
创建数据库表
使用Drift定义数据库表。以下是一个简单的任务表(TaskTable
)的定义:import 'package:drift/drift.dart'; class TaskTable extends Table { IntColumn get id => integer().autoIncrement()(); // 自增ID TextColumn get title => text()(); // 任务标题 TextColumn get description => text().nullable()(); // 任务描述,允许为空 BoolColumn get completed => boolean().withDefault(const Constant(false))(); // 是否完成,默认为false }
-
创建数据库类
定义一个继承自$_AppDatabase
的数据库类,并指定要使用的表和schema版本:import 'package:drift/drift.dart'; import 'package:drift_libsql/drift_libsql.dart'; import 'dart:io' as io; import 'package:path_provider/path_provider.dart'; part 'database.g.dart'; // Drift生成的代码 [@DriftDatabase](/user/DriftDatabase)(tables: [TaskTable]) class AppDatabase extends _$AppDatabase { AppDatabase(super.e); @override int get schemaVersion => 1; // 数据库版本 // 插入任务 Future<int> insertTask(TaskTableCompanion task) { return into(taskTable).insert(task); } // 查询所有任务 Future<List<Task>> getAllTasks() { return (select(taskTable)..orderBy([(t) => OrderingTerm.asc(t.id)])).get(); } // 更新任务 Future<int> updateTask(TaskTableCompanion task) { return update(taskTable).replace(task); } // 删除任务 Future<int> deleteTask(int id) { return (delete(taskTable)..where((t) => t.id.equals(id))).go(); } }
-
初始化数据库
在main.dart
中初始化不同类型的数据库实例(内存、本地、远程和副本)。这里我们使用path_provider
来获取应用的缓存目录路径,并根据不同的需求创建不同的数据库实例:import 'package:drift_libsql/drift_libsql.dart'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'database.dart'; // 引入上面定义的数据库类 const url = String.fromEnvironment("TURSO_URL"); // 远程数据库URL const token = String.fromEnvironment("TURSO_TOKEN"); // 认证令牌 late AppDatabase memoryDatabase; late AppDatabase localDatabase; late AppDatabase remoteDatabase; late AppDatabase replicaDatabase; Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); final dir = await getApplicationCacheDirectory(); // 获取应用缓存目录 // 初始化不同类型的数据库实例 memoryDatabase = AppDatabase(DriftLibsqlDatabase(":memory:")); // 内存数据库 localDatabase = AppDatabase(DriftLibsqlDatabase("${dir.path}/local.db")); // 本地数据库 remoteDatabase = AppDatabase(DriftLibsqlDatabase(url, authToken: token)); // 远程数据库 replicaDatabase = AppDatabase(DriftLibsqlDatabase( "${dir.path}/replica.db", syncUrl: url, authToken: token, readYourWrites: true, // 同步写操作 syncIntervalSeconds: 3, // 每3秒同步一次 )); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Libsql Dart Example')), body: Padding( padding: const EdgeInsets.all(24), child: Builder(builder: (context) { return Center( child: Column( children: [ FilledButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => Provider( create: (context) => LibsqlTaskRepository(memoryDatabase), child: const TaskList(), ), ), ); }, child: const Text("Memory"), ), const SizedBox(height: 16), FilledButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => Provider( create: (context) => LibsqlTaskRepository(localDatabase), child: const TaskList(), ), ), ); }, child: const Text("Local"), ), const SizedBox(height: 16), FilledButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => Provider( create: (context) => LibsqlTaskRepository(remoteDatabase), child: const TaskList(), ), ), ); }, child: const Text("Remote"), ), const SizedBox(height: 16), FilledButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => Provider( create: (context) => LibsqlTaskRepository(replicaDatabase), child: const TaskList(), ), ), ); }, child: const Text("Replica"), ), ], ), ); }), ), ), ); } }
-
任务列表页面
创建一个简单的任务列表页面TaskList
,用于展示和管理任务。你可以通过Provider
将TaskRepository
传递给页面,并使用StreamBuilder
或FutureBuilder
来显示任务数据:import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'repositories/task_repository.dart'; class TaskList extends StatelessWidget { const TaskList({super.key}); @override Widget build(BuildContext context) { final taskRepository = Provider.of<TaskRepository>(context); return Scaffold( appBar: AppBar(title: const Text('Task List')), body: FutureBuilder<List<Task>>( future: taskRepository.getAllTasks(), // 获取所有任务 builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('No tasks found')); } else { return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { final task = snapshot.data![index]; return ListTile( title: Text(task.title), subtitle: Text(task.description ?? 'No description'), trailing: Checkbox( value: task.completed, onChanged: (value) { taskRepository.updateTask( TaskTableCompanion( id: Value(task.id), completed: Value(value!), ), ); }, ), onLongPress: () { taskRepository.deleteTask(task.id); // 删除任务 }, ); }, ); } }, ), floatingActionButton: FloatingActionButton( onPressed: () async { final newTaskTitle = await _promptForTaskTitle(context); if (newTaskTitle != null && newTaskTitle.isNotEmpty) { await taskRepository.insertTask( TaskTableCompanion( title: Value(newTaskTitle), description: const Value(null), completed: const Value(false), ), ); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Task added!')), ); } }, child: const Icon(Icons.add), ), ); } Future<String?> _promptForTaskTitle(BuildContext context) async { return await showDialog<String>( context: context, builder: (context) => AlertDialog( title: const Text('Add Task'), content: TextField( decoration: const InputDecoration(hintText: 'Enter task title'), autofocus: true, onSubmitted: (value) { Navigator.of(context).pop(value); }, ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), TextButton( onPressed: () { Navigator.of(context).pop( (ModalRoute.of(context)?.widget as AlertDialog) .content .key ?.currentContext ?.findRenderObject() ?.debugDescribeChildren() ?.first ?.value as TextEditingController .text, ); }, child: const Text('Add'), ), ], ), ); } }
-
任务仓库类
创建一个TaskRepository
类来封装与数据库交互的逻辑。你可以根据不同的数据库实例(内存、本地、远程或副本)来选择不同的实现方式:import 'package:drift/drift.dart'; import 'package:drift_libsql_example/database.dart'; class LibsqlTaskRepository implements TaskRepository { final AppDatabase _db; LibsqlTaskRepository(this._db); @override Future<int> insertTask(TaskTableCompanion task) { return _db.insertTask(task); } @override Future<List<Task>> getAllTasks() { return _db.getAllTasks(); } @override Future<int> updateTask(TaskTableCompanion task) { return _db.updateTask(task); } @override Future<int> deleteTask(int id) { return _db.deleteTask(id); } } abstract class TaskRepository { Future<int> insertTask(TaskTableCompanion task); Future<List<Task>> getAllTasks(); Future<int> updateTask(TaskTableCompanion task); Future<int> deleteTask(int id); }
更多关于Flutter数据库管理插件drift_libsql的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html