SQLite" class="css-1occaib">SQLite数据库是基于事实和标准SQL的嵌入式数据库引擎,它是小型且经过时间考验的数据库引擎,sqflite软件包提供了许多函数,可以有效地与SQLite数据库一起使用,它提供了操作SQLite数据库引擎的标准方法。
在Android Studio中创建一个新的Flutter应用程序product_sqlite_app。
用无涯教程的 product_rest_app 代码替换默认的启动代码(main.dart)。
将assets文件夹从 product_nav_app 复制到 product_rest_app 并在* pubspec.yaml`文件内添加assets。
flutter: assets: - assets/appimages/floppy.png - assets/appimages/iphone.png - assets/appimages/laptop.png - assets/appimages/pendrive.png - assets/appimages/pixel.png - assets/appimages/tablet.png
在pubspec.yaml文件中配置sqflite软件包,如下所示-
dependencies: sqflite: any
在pubspec.yaml文件中配置path_provider软件包,如下所示-
dependencies: path_provider: any
此处,path_provider软件包用于获取系统的临时文件夹路径和应用程序的路径,使用 sqflite 的最新版本号代替任何。
Android Studio会提醒pubspec.yaml已更新。
单击"Get dependencies"选项。 Android studio将从互联网上获取该软件包,并为应用程序正确配置它。
在数据库中,无涯教程需要主键,id作为附加字段以及产品属性(如名称,价格等),因此,请在Product类中添加id属性。另外,添加新方法toMap将产品对象转换为Map对象。 fromMap和toMap用于对Product对象进行序列化和反序列化,并用于数据库操作方法中。
class Product { final int id; final String name; final String description; final int price; final String image; static final columns = ["id", "name", "description", "price", "image"]; Product(this.id, this.name, this.description, this.price, this.image); factory Product.fromMap(Map<String, dynamic> data) { return Product( data['id'], data['name'], data['description'], data['price'], data['image'], ); } Map<String, dynamic> toMap() => { "id": id, "name": name, "description": description, "price": price, "image": image }; }
在lib文件夹中创建一个新文件Database.dart,以编写SQLite的相关函数。
在Database.dart中导入必要的import语句。
import 'dart:async'; import 'dart:io'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart'; import 'Product.dart';
-
请注意以下几点-
async - 用于编写异步方法。
io - 用于访问文件和目录。
path - 用于访问与文件路径相关的dart核心实用程序函数。
path_provider - 用于获取临时路径和应用程序路径。
sqflite - 用于操作SQLite的数据库。
创建一个新的类SQLite的DbProvider
- 声明一个基于单例的静态SQLite的DbProvider对象,如下所示:
class SQLiteDbProvider { SQLiteDbProvider._(); static final SQLiteDbProvider db=SQLiteDbProvider._(); static Database _database; }
- 可以通过静态db变量访问SQLite的DBProvoider对象及其方法。
SQLiteDBProvoider.db.<emthod>
- 创建一个方法来获取类型为Future <Database>的数据库,创建产品表并在数据库本身创建期间加载初始数据。
Future<Database> get database async { if (_database != null) return _database; _database = await initDB(); return _database; } initDB() async { Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, "ProductDB.db"); return await openDatabase( path, version: 1, onOpen: (db) {}, onCreate: (Database db, int version) async { await db.execute( "CREATE TABLE Product (" "id INTEGER PRIMARY KEY," "name TEXT," "description TEXT," "price INTEGER," "image TEXT" ")" ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [1, "iPhone", "iPhone is the stylist phone ever", 1000, "iphone.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [2, "Pixel", "Pixel is the most feature phone ever", 800, "pixel.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [3, "Laptop", "Laptop is most productive development tool", 2000, "laptop.png"]\ ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [4, "Tablet", "Laptop is most productive development tool", 1500, "tablet.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [5, "Pendrive", "Pendrive is useful storage medium", 100, "pendrive.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [6, "Floppy Drive", "Floppy drive is useful rescue storage medium", 20, "floppy.png"] ); } ); }
在这里,无涯教程使用了以下方法-
- getApplicationDocumentsDirectory - 返回应用程序目录路径
- join - 用于创建系统特定的路径,无涯教程已经使用它来创建数据库路径。
- openDatabase - 用于打开SQLite的数据库。
- onOpen - 用于在打开数据库时编写代码
- onCreate - 用于在首次创建数据库时编写代码
- db.execute - 用于执行SQL查询。它接受一个查询。如果查询具有占位符(?),则它将接受值作为第二个参数中的列表。
编写getAllProducts来获取数据库中的所有产品-
Future<List<Product>> getAllProducts() async { final db = await database; List<Map> results = await db.query("Product", columns: Product.columns, orderBy: "id ASC"); List<Product> products = new List(); results.forEach((result) { Product product = Product.fromMap(result); products.add(product); }); return products; }
编写getProductById来获取特定于 id的产品
Future<Product> getProductById(int id) async { final db = await database; var result = await db.query("Product", where: "id=", whereArgs: [id]); return result.isNotEmpty ? Product.fromMap(result.first) : Null; }
在这里,无涯教程使用了where和whereArgs来应用过滤器。
创建三种方法-插入,更新和删除方法,以从数据库中插入,更新和删除产品。
insert(Product product) async { final db = await database; var maxIdResult = await db.rawQuery( "SELECT MAX(id)+1 as last_inserted_id FROM Product"); var id = maxIdResult.first["last_inserted_id"]; var result = await db.rawInsert( "INSERT Into Product (id, name, description, price, image)" " VALUES (?, ?, ?, ?, ?)", [id, product.name, product.description, product.price, product.image] ); return result; } update(Product product) async { final db = await database; var result = await db.update("Product", product.toMap(), where: "id=?", whereArgs: [product.id]); return result; } delete(int id) async { final db = await database; db.delete("Product", where: "id=?", whereArgs: [id]); }
Database.dart的最终代码如下-
import 'dart:async'; import 'dart:io'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart'; import 'Product.dart'; class SQLiteDbProvider { SQLiteDbProvider._(); static final SQLiteDbProvider db = SQLiteDbProvider._(); static Database _database; Future<Database> get database async { if (_database != null) return _database; _database = await initDB(); return _database; } initDB() async { Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, "ProductDB.db"); return await openDatabase( path, version: 1, onOpen: (db) {}, onCreate: (Database db, int version) async { await db.execute( "CREATE TABLE Product (" "id INTEGER PRIMARY KEY," "name TEXT," "description TEXT," "price INTEGER," "image TEXT"")" ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [1, "iPhone", "iPhone is the stylist phone ever", 1000, "iphone.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [2, "Pixel", "Pixel is the most feature phone ever", 800, "pixel.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [3, "Laptop", "Laptop is most productive development tool", 2000, "laptop.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [4, "Tablet", "Laptop is most productive development tool", 1500, "tablet.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [5, "Pendrive", "Pendrive is useful storage medium", 100, "pendrive.png"] ); await db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') values (?, ?, ?, ?, ?)", [6, "Floppy Drive", "Floppy drive is useful rescue storage medium", 20, "floppy.png"] ); } ); } Future<List<Product>> getAllProducts() async { final db = await database; List<Map> results = await db.query( "Product", columns: Product.columns, orderBy: "id ASC" ); List<Product> products = new List(); results.forEach((result) { Product product = Product.fromMap(result); products.add(product); }); return products; } Future<Product> getProductById(int id) async { final db = await database; var result = await db.query("Product", where: "id=", whereArgs: [id]); return result.isNotEmpty ? Product.fromMap(result.first) : Null; } insert(Product product) async { final db = await database; var maxIdResult = await db.rawQuery("SELECT MAX(id)+1 as last_inserted_id FROM Product"); var id = maxIdResult.first["last_inserted_id"]; var result = await db.rawInsert( "INSERT Into Product (id, name, description, price, image)" " VALUES (?, ?, ?, ?, ?)", [id, product.name, product.description, product.price, product.image] ); return result; } update(Product product) async { final db = await database; var result = await db.update( "Product", product.toMap(), where: "id=?", whereArgs: [product.id] ); return result; } delete(int id) async { final db = await database; db.delete("Product", where: "id=?", whereArgs: [id]); } }
更改主要方法以获取产品信息。
void main() { runApp(MyApp(products: SQLite的DbProvider.db.getAllProducts())); }
在这里,无涯教程使用了getAllProducts方法来从数据库中获取所有产品。
运行该应用程序并查看结果。它与先前的示例访问产品服务API相似,不同之处在于,产品信息是从本地SQLite的数据库存储和获取的。
参考链接
https://www.learnfk.com/flutter/flutter-database-concepts.html