移动应用行业中飞速发展的技术趋势不过是Google推出的跨平台SDK Flutter。凭借其跨平台和快速开发等特点,深受开发人员的喜爱,关注度不断上升。
Flutter 没有内置数据的相关方法,但是我们可以使用 SQLFile 插件将 SQLite 集成到 Flutter 应用程序中。
在本文,我们将讨论如何在 Flutter 应用程序中设置本地 SQLite 数据库。
SQLite是一个开源关系数据库。SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,您不需要在系统中配置。
就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。
SQFLite 是Flutter的插件,它支持 Android 和 iOS。
Flutter 不提供用于访问 SQLite 数据库的内置抽象。但是,使用SQFlite插件,可以在Android和iOS上访问SQLite数据库。该插件维护良好,并且也受到Flutter团队的推荐。
如果您不熟悉SQLite和SQL语句,请继续阅读 SQL教程,了解 SQLite 的基础知识。
在本文中,我们将演示在 Flutter 应用程序中使用 SQFlite 插件的示例(TODO App)
将以下依赖项添加到 pubspec.yml 并在终端中运行 “flutter packages get” 命令
sqflite: ^1.1.0 #sqflite packageflutter_simple_dependency_injection: ^1.0.1 # to perform dependency injectionpath_provider: ^0.5.0+1 #helper package used by database helper class to get the database file
此类将在应用程序的整个生命周期中使用。理想情况下,应与某种依赖注入技术一起使用。
import 'dart:io' as io;import 'package:path/path.dart';import 'package:path_provider/path_provider.dart';import 'package:sqflite/sqflite.dart';class DatabaseHelper { static final DatabaseHelper _instance = DatabaseHelper.internal(); factory DatabaseHelper() => _instance; static Database _db; DatabaseHelper.internal(); initDb() async { io.Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, "database_name.db"); _db = await openDatabase(path, version: 1, onCreate: _onCreate); } Database get db { return _db; } void _onCreate(Database db, int version) async { // When creating the db, create the table await db.execute( 'CREATE TABLE todos (id INTEGER PRIMARY KEY AUTOINCREMENT,''item_name TEXT,' 'date_created TEXT')'; }}
在上面的 DatabaseHelper 类中, initDb() 方法进行初始化。首次创建数据库时会调用 onCreate()。
import 'dart:async';import 'package:eknumber/utils/database_helper.dart';import 'package:flutter_simple_dependency_injection/injector.dart';class Injection { static DatabaseHelper _databaseHelper = DatabaseHelper(); static Injector injector; static Future initInjection() async { await _databaseHelper.initDb(); injector = Injector.getInjector(); injector.map<DatabaseHelper>((i) => _databaseHelper, isSingleton: true); }}
上面的类确保在应用程序的整个生命周期中只有一个数据库实例可用。在其他地方你需要使用数据库,可以通过执行以下操作轻松的获取到它:
DatabaseHelper _databaseHelper = Injection.injector.get();
在本示例中,我们将创建一个简单的数据模型,该模型具有很少的属性和很少的方法,这些属性和方法将在对DB表执行CRUD操作时使用。
class Todo{ int id; String itemName; String dateCreated; Todo( {this.id, this.itemName, this.dateCreated}) //to be used when inserting a row in the table Map<String, dynamic> toMapWithoutId() { final map = Map<String, dynamic>(); map["item_name"] = itemName; map["date_created"] = dateCreated; return map; }Map<String, dynamic> toMap() { final map = Map<String, dynamic>(); map["id"] = id; map["item_name"] = itemName; map["date_created"] = dateCreated; return map; } //to be used when converting the row into object factory Todo.fromMap(Map<String, dynamic> data) => Todo( id: data['id'], itemName: data['item_name'], dateCreated: data['date_created'] );}
现在,我们已经建立了基本结构以及依赖注入,我们可以轻松地在模型上执行CRUD操作
要在表格中创建一行
Future<int> create(String itemName, String dateCreated) async{ final todo = Todo(itemName: itemName, dateCreated: dateCreated); //databaseHelper has been injected in the class int id = await _databaseHelper.db.insert(“todos”, todo.toMapWithoutId()); return id;}
要读取一条记录,我们将编写一个原始SQL查询。该查询将返回List。这些 Map 不过是表中的行,我们将使用 Todo.fromMap() 工厂方法来获取所需的对象。
Future<int> getItemById(int id) async{ //databaseHelper has been injected in the class List<Map> list = await _databaseHelper.db.rawQuery("Select * from todos where id = ?",[id]); if(list.length > 0){ return Todo.fromMap(list[0]); } return null;}
若要更新数据,请使用 SQFlite 包中的 update() 方法
Future<int> updateItem(Todo item) async { //databaseHelper has been injected in the class return await _databaseHelper.db.update("todos", item.toMap(), where: "id = ?", whereArgs: [item.id]);}
删除相当简单。只需在where子句中传递列名及其值即可
Future<int> deleteItem(int id) async { return await _databaseHelper.db.delete("todos", where: "id = ?", whereArgs: [id]);}
为了在应用启动时初始化数据库,我们需要调用 Injection 类的 init() 方法。
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Injection.initInjection(); runApp(MyApp());}