教程 > flutter 教程 > 阅读:95

flutter 数据库概念——迹忆客-ag捕鱼王app官网

flutter 提供了许多高级软件包来处理数据库。 最重要的软件包是

  • sqflite - 用于访问和操作 sqlite 数据库,以及
  • firebase_database - 用于访问和操作来自 google 的云托管 nosql 数据库。

在本章中,让我们详细讨论它们中的每一个。

sqlite

sqlite 数据库是事实上和标准的基于 sql 的嵌入式数据库引擎。它是小型且经过时间考验的数据库引擎。 sqflite 包提供了很多功能来高效地使用 sqlite 数据库。它提供了操作 sqlite 数据库引擎的标准方法。 sqflite 包提供的核心功能如下

  • 创建/打开(opendatabase 方法)一个 sqlite 数据库。
  • 针对 sqlite 数据库执行 sql 语句(执行方法)。
  • 高级查询方法(查询方法)可减少从 sqlite 数据库查询和获取信息所需的代码。

让我们创建一个产品应用程序,使用 sqflite 包从标准 sqlite 数据库引擎存储和获取产品信息,并了解 sqlite 数据库和 sqflite 包背后的概念。

  • 在 android studio 中创建一个新的 flutter 应用程序 product_sqlite_app。
  • 将默认启动代码 (main.dart) 替换为我们的 product_rest_app 代码。
  • 将 assets 文件夹从 product_nav_app 复制到 product_rest_app 并在 *pubspec.yaml` 文件中添加资源。
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

在任何地方使用 sqflite 的最新版本号

在pubspec.yaml文件中配置path_provider包如下所示

dependencies: path_provider: any

在这里,path_provider 包用于获取系统的临时文件夹路径和应用程序的路径。

android studio 会提醒 pubspec.yaml 已更新。

flutter sqlite updated

单击获取依赖项选项。 android studio 将从 internet 获取包并为应用程序正确配置它。

在数据库中,我们需要主键、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 data) {
      return product( 
         data['id'], 
         data['name'], 
         data['description'], 
         data['price'], 
         data['image'], 
      ); 
   } 
   map tomap() => {
      "id": id, 
      "name": name, 
      "description": description, 
      "price": price, 
      "image": image 
   }; 
}

在 lib 文件夹中新建一个文件 database.dart 来编写sqlite相关的功能。

在 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';

请注意以下几点 -

  • async用于编写异步方法。
  • io用于访问文件和目录。
  • path用于访问与文件路径相关的 dart 核心实用程序功能。
  • path_provider用于获取临时和应用程序路径。
  • sqflite用于操作 sqlite 数据库。

创建一个新类sqlitedbprovider

声明一个基于单例的静态 sqlitedbprovider 对象,如下所示 -

class sqlitedbprovider {
sqlitedbprovider._();
static final sqlitedbprovider db = sqlitedbprovider._();
static database _database;
}

sqlitedbprovoider 对象及其方法可以通过静态 db 变量访问。

sqlitedbprovoider.db.

创建一个方法来获取 future 类型的数据库(future 选项)。在创建数据库本身的过程中创建产品表并加载初始数据。

future 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 查询。它接受查询。如果查询有占位符 (?),则它接受值作为第二个参数中的列表。

编写一个方法来获取数据库中的所有产品

future> getallproducts() async { 
   final db = await database; 
   list

在这里,我们做了以下工作 -

  • 使用查询方法获取所有产品信息。query 提供了查询表信息的快捷方式,而无需编写整个查询。query 方法将通过使用我们的输入(如列、orderby 等)自行生成正确的查询,
  • 使用 product 的 frommap 方法通过循环结果对象来获取产品详细信息,结果对象包含表中的所有行。

编写一个方法来获取特定于id的产品

future 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 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> getallproducts() async {
      final db = await database; 
      list

更改获取产品信息的主要方法。

void main() {
   runapp(myapp(products: sqlitedbprovider.db.getallproducts())); 
}

在这里,我们使用 getallproducts 方法从数据库中获取所有产品。

运行应用程序并查看结果。它将类似于前面的示例,访问产品服务 api,除了产品信息是从本地 sqlite 数据库存储和获取的。


云防火墙

firebase 是一个 baas 应用程序开发平台。它提供了许多特性来加速移动应用程序的开发,如身份验证服务、云存储等,firebase 的主要特性之一是 cloud firestore,一个基于云的实时 nosql 数据库。

flutter 提供了一个特殊的包 cloud_firestore 来使用 cloud firestore 进行编程。让我们在 cloud firestore 中创建一个在线产品商店,并创建一个应用程序来访问产品商店。

在 android studio 中创建一个新的 flutter 应用程序 product_firebase_app。

将默认启动代码 (main.dart) 替换为我们的product_rest_app代码。

将 product.dart 文件从 product_rest_app 复制到 lib 文件夹中。

class product { 
   final string name; 
   final string description; 
   final int price; 
   final string image; 
   
   product(this.name, this.description, this.price, this.image); 
   factory product.frommap(map json) {
      return product( 
         json['name'], 
         json['description'], 
         json['price'], 
         json['image'], 
      ); 
   }
}

将 assets 文件夹从 product_rest_app 复制到 product_firebase_app 并在 pubspec.yaml 文件中添加资源。

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 文件中配置 cloud_firestore 包,如下所示 -

dependencies: cloud_firestore: ^0.9.13 1

在这里,使用最新版本的 cloud_firestore 包。

android studio 将提醒 pubspec.yaml 已更新,如下所示 -

cloud firestore 包

单击获取依赖项选项。android studio 将从 internet 获取包并为应用程序正确配置它。

使用以下步骤在 firebase 中创建一个项目 -

  • 通过在 https://firebase.google.com/pricing/ 选择免费计划来创建一个 firebase 帐户。
  • 创建 firebase 帐户后,它将重定向到项目概览页面。它列出了所有基于 firebase 的项目,并提供了一个创建新项目的选项。
  • 单击添加项目,它将打开一个项目创建页面。
  • 输入 products app db 作为项目名称,然后单击 create project 选项。
  • 转到 *firebase 控制台。
  • 单击项目概述。它会打开项目概览页面。
  • 点击安卓图标。它将打开特定于 android 开发的项目设置。
  • 输入 android 包名称,com.tutorialspoint.flutterapp.product_firebase_app。
  • 单击注册应用程序。它会生成一个项目配置文件 google_service.json。
  • 下载 google_service.json,然后将其移动到项目的 android/app 目录中。该文件是我们的应用程序和 firebase 之间的连接。
  • 打开 android/app/build.gradle 并包含以下代码 -
apply plugin: 'com.google.gms.google-services'

打开 android/build.gradle 并包含以下配置 -

buildscript {
repositories {
// ...
}
dependencies {
// ...
classpath 'com.google.gms:google-services:3.2.1' // new
}
}

在这里,插件和类路径用于读取 google_service.json 文件。

打开 android/app/build.gradle 并包含以下代码。

android {
   defaultconfig { 
      ... 
      multidexenabled true 
   } 
   ...
}
dependencies {
   ... 
   compile 'com.android.support: multidex:1.0.3' 
}

此依赖项使 android 应用程序能够使用多个 dex 功能。

  • 按照 firebase 控制台中的其余步骤操作,或者直接跳过它。

使用以下步骤在新创建的项目中创建产品商店 -

  • 转到 firebase 控制台。
  • 打开新创建的项目。
  • 单击左侧菜单中的数据库选项。
  • 单击创建数据库选项。
  • 单击以测试模式启动,然后单击启用。
  • 单击添加集合。输入产品作为集合名称,然后单击下一步。
  • 输入示例产品信息,如图所示

样品产品信息

使用添加文档选项添加附加产品信息。

打开 main.dart 文件并导入 cloud firestore 插件文件并删除 http 包。

import 'package:cloud_firestore/cloud_firestore.dart';

移除 parseproducts 并更新 fetchproducts 以从 cloud firestore 而不是产品服务 api 获取产品。

stream fetchproducts() {
return firestore.instance.collection('product').snapshots(); }

在这里,firestore.instance.collection 方法用于访问云存储中可用的产品集合。firestore.instance.collection 提供了许多选项来过滤集合以获取必要的文档。但是,我们没有应用任何过滤器来获取所有产品信息。

cloud firestore 通过 dart stream 概念提供集合,因此将 myapp 和 myhomepage 小部件中的产品类型从 future> 修改为 stream

myhomepage 小部件的构建方法更改为使用 streambuilder 而不是 futurebuilder

@override 
widget build(buildcontext context) {
   return scaffold(
      appbar: appbar(title: text("product navigation")), 
      body: center(
         child: streambuilder(
            stream: products, builder: (context, snapshot) {
               if (snapshot.haserror) print(snapshot.error); 
               if(snapshot.hasdata) {
                  list 
                  documents = snapshot.data.documents; 
                  
                  list 
                  items = list(); 
                  
                  for(var i = 0; i < documents.length; i  ) { 
                     documentsnapshot document = documents[i]; 
                     items.add(product.frommap(document.data)); 
                  } 
                  return productboxlist(items: items);
               } else { 
                  return center(child: circularprogressindicator()); 
               }
            }, 
         ), 
      )
   ); 
}

在这里,我们以 list 类型获取产品信息。由于我们的小部件 productboxlist 与文档不兼容,因此我们将文档转换为 list 类型并进一步使用它。

最后,运行应用程序并查看结果。由于我们使用了与sqlite 应用程序相同的产品信息,并且仅更改了存储介质,因此生成的应用程序看起来与sqlite 应用程序应用程序相同。

查看笔记

扫码一下
查看教程更方便
网站地图