Flutter - แนวคิดฐานข้อมูล

Flutter มีแพ็คเกจขั้นสูงมากมายสำหรับทำงานกับฐานข้อมูล แพ็คเกจที่สำคัญที่สุด ได้แก่ -

  • sqflite - ใช้เพื่อเข้าถึงและจัดการฐานข้อมูล SQLite และ

  • firebase_database - ใช้เพื่อเข้าถึงและจัดการฐานข้อมูล NoSQL ที่โฮสต์บนคลาวด์จาก Google

ในบทนี้ให้เราพิจารณารายละเอียดแต่ละข้อ

SQLite

ฐานข้อมูล SQLite เป็นเอ็นจิ้นฐานข้อมูลฝังตัวที่อิงตามข้อเท็จจริงและมาตรฐานของ SQL เป็นเครื่องมือฐานข้อมูลขนาดเล็กและผ่านการทดสอบตามเวลา แพ็คเกจ sqflite มีฟังก์ชันมากมายในการทำงานอย่างมีประสิทธิภาพกับฐานข้อมูล SQLite มีวิธีการมาตรฐานในการจัดการเอ็นจินฐานข้อมูล SQLite ฟังก์ชันหลักที่จัดเตรียมโดยแพ็คเกจ sqflite มีดังต่อไปนี้ -

  • สร้าง / เปิด (วิธีการ openDatabase) ฐานข้อมูล SQLite

  • ดำเนินการคำสั่ง SQL (วิธีดำเนินการ) กับฐานข้อมูล SQLite

  • วิธีการสืบค้นขั้นสูง (วิธีการสืบค้น) เพื่อลดรหัสที่จำเป็นในการสืบค้นและรับข้อมูลจากฐานข้อมูล SQLite

ให้เราสร้างแอปพลิเคชันผลิตภัณฑ์เพื่อจัดเก็บและดึงข้อมูลผลิตภัณฑ์จากเอ็นจินฐานข้อมูล SQLite มาตรฐานโดยใช้แพ็คเกจ sqflite และทำความเข้าใจแนวคิดเบื้องหลังฐานข้อมูล SQLite และแพ็คเกจ sqflite

  • สร้างแอปพลิเคชัน Flutter ใหม่ใน Android studio 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
  • กำหนดค่าแพ็คเกจ sqflite ในไฟล์ pubspec.yaml ดังที่แสดงด้านล่าง -

dependencies: sqflite: any

ใช้หมายเลขเวอร์ชันล่าสุดของ sqflite แทนใด ๆ

  • กำหนดค่าแพ็คเกจ path_provider ในไฟล์ pubspec.yaml ดังที่แสดงด้านล่าง -

dependencies: path_provider: any
  • ที่นี่แพ็กเกจ path_provider ใช้เพื่อรับพา ธ โฟลเดอร์ชั่วคราวของระบบและพา ธ ของแอ็พพลิเคชัน ใช้เลขเวอร์ชันล่าสุดsqfliteในสถานที่ใด ๆ

  • Android studio จะแจ้งเตือนว่ามีการอัปเดต pubspec.yaml

  • คลิกตัวเลือกรับการอ้างอิง Android studio จะได้รับแพ็คเกจจากอินเทอร์เน็ตและกำหนดค่าให้เหมาะสมกับแอปพลิเคชัน

  • ในฐานข้อมูลเราต้องการคีย์หลัก id เป็นฟิลด์เพิ่มเติมพร้อมกับคุณสมบัติของผลิตภัณฑ์เช่นชื่อราคา ฯลฯ ดังนั้นให้เพิ่มคุณสมบัติ id ในคลาสผลิตภัณฑ์ นอกจากนี้ให้เพิ่มวิธีการใหม่ toMap เพื่อแปลงวัตถุผลิตภัณฑ์เป็นวัตถุแผนที่ fromMap และ toMap ถูกใช้เพื่อทำให้เป็นอนุกรมและแยกชิ้นส่วนของวัตถุผลิตภัณฑ์และใช้ในวิธีการจัดการฐานข้อมูล

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 
   }; 
}
  • สร้างไฟล์ใหม่ Database.dart ในโฟลเดอร์ lib เพื่อเขียนฟังก์ชันที่เกี่ยวข้องกับ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 core ที่เกี่ยวข้องกับเส้นทางไฟล์

    • path_provider ใช้เพื่อรับเส้นทางชั่วคราวและแอปพลิเคชัน

    • sqflite ใช้เพื่อจัดการฐานข้อมูล SQLite

  • สร้างชั้นเรียนใหม่ SQLiteDbProvider

  • ประกาศอ็อบเจ็กต์ SQLiteDbProvider แบบคงที่ตามซิงเกิลตันตามที่ระบุด้านล่าง -

class SQLiteDbProvider { 
   SQLiteDbProvider._(); 
   static final SQLiteDbProvider db = SQLiteDbProvider._(); 
   static Database _database; 
}
  • วัตถุ SQLiteDBProvoider และวิธีการสามารถเข้าถึงได้ผ่านตัวแปร db แบบคงที่

SQLiteDBProvoider.db.<emthod>
  • สร้างวิธีการรับฐานข้อมูล (ตัวเลือกในอนาคต) ประเภทอนาคต <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 ยอมรับแบบสอบถาม หากแบบสอบถามมีตัวยึดตำแหน่ง (?) ก็จะยอมรับค่าเป็นรายการในอาร์กิวเมนต์ที่สอง

  • เขียนวิธีการรับผลิตภัณฑ์ทั้งหมดในฐานข้อมูล -

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; 
}
  • ที่นี่เราได้ทำสิ่งต่อไปนี้ -

    • ใช้วิธีการสืบค้นเพื่อดึงข้อมูลผลิตภัณฑ์ทั้งหมด คิวรีให้ทางลัดในการสืบค้นข้อมูลตารางโดยไม่ต้องเขียนคิวรีทั้งหมด วิธีการสืบค้นจะสร้างแบบสอบถามที่เหมาะสมเองโดยใช้อินพุตของเราเช่นคอลัมน์ orderBy ฯลฯ

    • ใช้เมธอด fromMap ของผลิตภัณฑ์เพื่อรับรายละเอียดผลิตภัณฑ์โดยการวนซ้ำวัตถุผลลัพธ์ซึ่งเก็บแถวทั้งหมดในตาราง

  • เขียนวิธีการรับผลิตภัณฑ์เฉพาะสำหรับ 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: SQLiteDbProvider.db.getAllProducts())); 
}
  • ที่นี่เราได้ใช้เมธอด getAllProducts เพื่อดึงข้อมูลผลิตภัณฑ์ทั้งหมดจากฐานข้อมูล

  • เรียกใช้แอปพลิเคชันและดูผลลัพธ์ จะคล้ายกับตัวอย่างก่อนหน้านี้Accessing Product service APIยกเว้นข้อมูลผลิตภัณฑ์จะถูกจัดเก็บและดึงมาจากฐานข้อมูล SQLite ในเครื่อง

Cloud Firestore

Firebase เป็นแพลตฟอร์มการพัฒนาแอป BaaS มีคุณสมบัติมากมายเพื่อเพิ่มความเร็วในการพัฒนาแอปพลิเคชันมือถือเช่นบริการตรวจสอบสิทธิ์พื้นที่เก็บข้อมูลบนคลาวด์เป็นต้นหนึ่งในคุณสมบัติหลักของ Firebase คือ Cloud Firestore ซึ่งเป็นฐานข้อมูล NoSQL แบบเรียลไทม์บนคลาวด์

Flutter จัดเตรียมแพ็คเกจพิเศษ cloud_firestore เพื่อเขียนโปรแกรมด้วย Cloud Firestore ให้เราสร้างที่เก็บสินค้าออนไลน์ใน Cloud Firestore และสร้างแอปพลิเคชันเพื่อเข้าถึงที่เก็บสินค้า

  • สร้างแอปพลิเคชัน Flutter ใหม่ใน Android studio, 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<String, dynamic> 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
  • กำหนดค่าแพ็คเกจ cloud_firestore ในไฟล์ pubspec.yaml ดังที่แสดงด้านล่าง -

dependencies: cloud_firestore: ^0.9.13+1
  • ที่นี่ใช้แพคเกจ cloud_firestore เวอร์ชันล่าสุด

  • Android studio จะแจ้งเตือนว่ามีการอัปเดต pubspec.yaml ดังที่แสดงไว้ที่นี่ -

  • คลิกตัวเลือกรับการอ้างอิง Android studio จะได้รับแพ็คเกจจากอินเทอร์เน็ตและกำหนดค่าให้เหมาะสมกับแอปพลิเคชัน

  • สร้างโครงการใน Firebase โดยใช้ขั้นตอนต่อไปนี้ -

    • สร้างบัญชี Firebase โดยเลือกแผนบริการฟรีที่ https://firebase.google.com/pricing/.

    • เมื่อสร้างบัญชี Firebase แล้วบัญชีจะเปลี่ยนเส้นทางไปยังหน้าภาพรวมโครงการ โดยแสดงรายการโครงการที่ใช้ Firebase ทั้งหมดและมีตัวเลือกในการสร้างโครงการใหม่

    • คลิกเพิ่มโครงการและจะเปิดหน้าการสร้างโครงการ

    • ป้อน db ของแอปผลิตภัณฑ์เป็นชื่อโปรเจ็กต์แล้วคลิกตัวเลือกสร้างโปรเจ็กต์

    • ไปที่คอนโซล * Firebase

    • คลิกภาพรวมโครงการ จะเปิดหน้าภาพรวมโครงการ

    • คลิกไอคอน android จะเปิดการตั้งค่าโครงการเฉพาะสำหรับการพัฒนา 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 Console หรือข้ามไป

  • สร้างที่เก็บสินค้าในโครงการที่สร้างขึ้นใหม่โดยใช้ขั้นตอนต่อไปนี้ -

    • ไปที่คอนโซล Firebase

    • เปิดโครงการที่สร้างขึ้นใหม่

    • คลิกตัวเลือกฐานข้อมูลในเมนูด้านซ้าย

    • คลิกตัวเลือกสร้างฐานข้อมูล

    • คลิกเริ่มในโหมดทดสอบจากนั้นเปิดใช้งาน

    • คลิกเพิ่มคอลเลกชัน ป้อนผลิตภัณฑ์เป็นชื่อคอลเลกชันจากนั้นคลิกถัดไป

    • ป้อนข้อมูลผลิตภัณฑ์ตัวอย่างตามภาพที่นี่ -

  • เพิ่มข้อมูลผลิตภัณฑ์เพิ่มเติมโดยใช้ตัวเลือกเพิ่มเอกสาร

  • เปิดไฟล์ main.dart และนำเข้าไฟล์ปลั๊กอิน Cloud Firestore และลบแพ็กเกจ http

import 'package:cloud_firestore/cloud_firestore.dart';
  • ลบ parseProducts และอัปเดต fetchProducts เพื่อดึงข้อมูลผลิตภัณฑ์จาก Cloud Firestore แทน Product service API

Stream<QuerySnapshot> fetchProducts() { 
   return Firestore.instance.collection('product').snapshots(); }
  • ที่นี่เมธอด Firestore.instance.collection ใช้เพื่อเข้าถึงคอลเลกชันผลิตภัณฑ์ที่มีอยู่ในร้านค้าบนคลาวด์ Firestore.instance.collection มีตัวเลือกมากมายในการกรองคอลเลกชันเพื่อรับเอกสารที่จำเป็น แต่เราไม่ได้ใช้ตัวกรองใด ๆ เพื่อรับข้อมูลผลิตภัณฑ์ทั้งหมด

  • Cloud Firestore จัดเตรียมคอลเลกชันผ่านแนวคิด Dart Stream และแก้ไขประเภทผลิตภัณฑ์ในวิดเจ็ต MyApp และ MyHomePage จาก Future <list <Product>> เป็น Stream <QuerySnapshot>

  • เปลี่ยนวิธีการสร้างของวิดเจ็ต MyHomePage เพื่อใช้ StreamBuilder แทน FutureBuilder

@override 
Widget build(BuildContext context) {
   return Scaffold(
      appBar: AppBar(title: Text("Product Navigation")), 
      body: Center(
         child: StreamBuilder<QuerySnapshot>(
            stream: products, builder: (context, snapshot) {
               if (snapshot.hasError) print(snapshot.error); 
               if(snapshot.hasData) {
                  List<DocumentSnapshot> 
                  documents = snapshot.data.documents; 
                  
                  List<Product> 
                  items = List<Product>(); 
                  
                  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()); 
               }
            }, 
         ), 
      )
   ); 
}
  • ที่นี่เราได้ดึงข้อมูลผลิตภัณฑ์เป็นประเภทรายการ <DocumentSnapshot> เนื่องจากวิดเจ็ต ProductBoxList ของเราไม่สามารถใช้งานร่วมกับเอกสารได้เราจึงได้แปลงเอกสารเป็นประเภท List <Product> และใช้ต่อไป

  • สุดท้ายเรียกใช้แอปพลิเคชันและดูผลลัพธ์ เนื่องจากเราได้ใช้ข้อมูลผลิตภัณฑ์เดียวกันกับแอปพลิเคชัน SQLiteและเปลี่ยนสื่อจัดเก็บข้อมูลเท่านั้นแอปพลิเคชันที่ได้จะมีลักษณะเหมือนกับแอปพลิเคชันแอปพลิเคชัน SQLite