مفهوم پایگاه داده در برنامه نویسی فلاتر 

3 سال پیش

 مفهوم پایگاه داده در برنامه نویسی فلاتر 

در این درس از آموزش های برنامه نویسی سایت سورس باران، با مفهوم پایگاه داده در برنامه نویسی فلاتر در خدمت شما هستیم.

پکیج های پیشرفته بسیاری را برای کار با پایگاه داده در برنامه نویسی فلاتر فراهم می باشد. مهمترین پکیج ها عبارتند از:

  • sqflite – برای دسترسی و دستکاری پایگاه داده SQLite استفاده می شود ، و
  • firebase_database – برای دسترسی و دستکاری پایگاه داده NoSQL میزبان ابر از Google استفاده می شود.

در این درس، اجازه دهید هر یک از آنها را به طور مفصل مورد بحث قرار دهیم.

SQLite

پایگاه داده SQLite موتور دیتابیس تعبیه شده واقعی و مبتنی بر SQL است. این موتور پایگاه داده کوچک و با آزمایش زمان است. بسته sqflite قابلیت های بسیاری برای کارایی کارآمد با پایگاه داده SQLite را فراهم می کند. این روش های استاندارد برای دستکاری موتور پایگاه داده SQLite را فراهم می کند. عملکرد اصلی ارائه شده توسط بسته sqflite به شرح زیر است –

  • یک پایگاه داده SQLite ایجاد / باز کنید (روش openDatabase).
  • دستور SQL (روش اجرا) را در برابر پایگاه داده SQLite اجرا کنید.
  • روشهای جستجوی پیشرفته (query method) برای کاهش کد مورد نیاز برای پرس و جو و دریافت اطلاعات از پایگاه داده SQLite.

بیایید یک برنامه برای ذخیره و واکشی اطلاعات محصول از یک موتور استاندارد پایگاه داده SQLite با استفاده از بسته sqflite ایجاد کنیم و مفهوم موجود در پایگاه داده SQLite و بسته sqflite را درک کنیم.

  • یک برنامه فلاتر جدید در Android studio ، product_sqlite_app ایجاد کنید.
  • کد راه اندازی پیش فرض (main.dart) را با کد product_rest_app ما جایگزین کنید.
  • پوشه assets را از Product_nav_app در Product_rest_app کپی کرده و assets را در داخل پرونده * 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 به روز شده است.

Updated

  • گزینه دریافت وابستگی ها را کلیک کنید. Android studio بسته را از اینترنت دریافت کرده و به درستی برای برنامه پیکربندی می کند.
  • در پایگاه داده در برنامه نویسی فلاتر ، ما به کلید اصلی، شناسه به عنوان فیلد اضافی همراه با ویژگی های محصول مانند نام، قیمت و غیره نیاز داریم، بنابراین ویژگی شناسه را در کلاس محصول اضافه کنید. همچنین، برای تبدیل شی product محصول به شی نقشه یک متد جدید به toMap اضافه کنید. fromMap و toMap برای serialize و de- serialize شی 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 
   }; 
}

 

  • برای نوشتن قابلیت های مربوط به SQLite، یک فایل جدید ایجاد کنید، Database.dart در پوشه lib.
  • دستورات لازم را در 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 برای دسترسی به تابع اصلی هسته دارت مربوط به مسیرهای فایل استفاده می شود.
  • path_provider برای بدست آوردن مسیر موقت و برنامه استفاده می شود.
  • sqflite برای دستکاری پایگاه داده SQLite استفاده می شود.

 

یک کلاس جدید SQLiteDbProvider ایجاد کنید

همانطور که در زیر مشخص شده است، یک مورد استاتیک SQLiteDbProvider مبتنی بر Singleton را اعلان کنید –

class SQLiteDbProvider { 
   SQLiteDbProvider._(); 
   static final SQLiteDbProvider db = SQLiteDbProvider._(); 
   static Database _database; 
}

شی SQLiteDBProvoider و متد آن از طریق متغیر db استاتیک قابل دسترسی است.

SQLiteDBProvoider.db.<emthod>

 

یک متد برای دریافت پایگاه داده (گزینه Future) از نوع <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 (?, ?, ?, ?, ?)", 
            [۱, "iPhone", "iPhone is the stylist phone ever", 1000, "iphone.png"]
         ); 
         await db.execute(
            "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
            values (?, ?, ?, ?, ?)", 
            [۲, "Pixel", "Pixel is the most feature phone ever", 800, "pixel.png"]
         ); 
         await db.execute(
            "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
            values (?, ?, ?, ?, ?)", 
            [۳, "Laptop", "Laptop is most productive development tool", 2000, "laptop.png"]\
         ); 
         await db.execute( 
            "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
            values (?, ?, ?, ?, ?)", 
            [۴, "Tablet", "Laptop is most productive development tool", 1500, "tablet.png"]
         );
         await db.execute( 
            "INSERT INTO Product 
            ('id', 'name', 'description', 'price', 'image') 
            values (?, ?, ?, ?, ?)", 
            [۵, "Pendrive", "Pendrive is useful storage medium", 100, "pendrive.png"]
         );
         await db.execute( 
            "INSERT INTO Product 
            ('id', 'name', 'description', 'price', 'image') 
            values (?, ?, ?, ?, ?)", 
            [۶, "Floppy Drive", "Floppy drive is useful rescue storage medium", 20, "floppy.png"]
         ); 
      }
   ); 
}

 

در اینجا، ما از متد های زیر استفاده کرده ایم –

  • getApplicationDocumentsDirectory – مسیر پوشه برنامه را برمی گرداند
  • join – برای ایجاد مسیر خاص سیستم استفاده می شود. ما از آن برای ایجاد مسیر پایگاه داده استفاده کرده ایم.
  • openDatabase – برای باز کردن یک پایگاه داده SQLite استفاده می شود
  • onOpen – برای نوشتن کد هنگام باز کردن یک پایگاه داده استفاده می شود
  • onCreate – برای نوشتن کد هنگام ایجاد پایگاه داده برای اولین بار استفاده می شود
  • db.execute – برای اجرای نمایش داده های SQL استفاده می شود. این یک کوئری را می پذیرد. اگر کوئری placeholder داشته باشد، مقادیر را به عنوان لیست در آرگومان دوم می پذیرد.

یک روش برای به دست آوردن همه محصولات در پایگاه داده بنویسید –

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 و غیره  را ایجاد می کند.

با استفاده از روش Product fromMap ، جزئیات محصول را با حلقه کردن  نتایج، که تمام ردیف های جدول را در خود نگه می دارد، بدست آورید.

برای بدست آوردن محصول خاص شناسه، روشی بنویسید

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 (?, ?, ?, ?, ?)", 
               [۱, "iPhone", "iPhone is the stylist phone ever", 1000, "iphone.png"]
            ); 
            await db.execute( 
               "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
               values (?, ?, ?, ?, ?)", 
               [۲, "Pixel", "Pixel is the most feature phone ever", 800, "pixel.png"]
            );
            await db.execute(
               "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
               values (?, ?, ?, ?, ?)", 
               [۳, "Laptop", "Laptop is most productive development tool", 2000, "laptop.png"]
            ); 
            await db.execute( 
               "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
               values (?, ?, ?, ?, ?)", 
               [۴, "Tablet", "Laptop is most productive development tool", 1500, "tablet.png"]
            ); 
            await db.execute( 
               "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
               values (?, ?, ?, ?, ?)", 
               [۵, "Pendrive", "Pendrive is useful storage medium", 100, "pendrive.png"]
            );
            await db.execute( 
               "INSERT INTO Product ('id', 'name', 'description', 'price', 'image') 
               values (?, ?, ?, ?, ?)", 
               [۶, "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 برای واکشی همه محصولات از پایگاه داده استفاده کرده ایم.

برنامه را اجرا کرده و نتایج را مشاهده کنید. این همانند مثال قبلی، دسترسی به سرویس API خدمات است، با این تفاوت که اطلاعات محصول از پایگاه داده محلی SQLite ذخیره شده و واکشی می شود.

Cloud Firestore

Firebase یک سکوی توسعه برنامه BaaS است. این ویژگی بسیاری را برای سرعت بخشیدن به توسعه برنامه های تلفن همراه مانند سرویس احراز هویت، ذخیره سازی ابری و غیره فراهم می کند. یکی از ویژگی های اصلی Firebase Cloud Firestore است که یک پایگاه داده مبتنی بر ابر در زمان واقعی NoSQL است.

فلاتر یک پکیج ویژه، cloud_firestore برای برنامه ریزی با Cloud Firestore فراهم می کند. بگذارید یک فروشگاه آنلاین کالا در Cloud Firestore ایجاد کنیم و یک برنامه کاربردی برای دسترسی به فروشگاه کالا ایجاد کنیم.

  • یک برنامه فلاتر جدید در 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'], 
      ); 
   }
}

 

همانطور که در زیر نشان داده شده، پکیج cloud_firestore را در فایل pubspec.yaml پیکربندی کنید –

dependencies: cloud_firestore: ^0.9.13+1

 

در اینجا، از آخرین نسخه پکیج cloud_firestore استفاده کنید.

Android studio هشدار می دهد pubspec.yaml به روز شده است همانطور که در اینجا نشان داده شده است –

 

Cloud Firestore Package

گزینه Get dependencies را کلیک کنید. Android studio بسته را از اینترنت دریافت کرده و به درستی برای برنامه پیکربندی می کند.

با استفاده از مراحل زیر یک پروژه در Firebase ایجاد کنید –

  • با انتخاب طرح رایگان در https://firebase.google.com/pricing/ حساب Firebase ایجاد کنید.
  • پس از ایجاد حساب 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' 
}

 

این dependency برنامه اندروید را قادر می سازد تا از چندین قابلیت dex استفاده کند.

مراحل باقیمانده را در Firebase Console دنبال کنید یا فقط از آن صرف نظر کنید.

با استفاده از مراحل زیر یک فروشگاه محصول در پروژه تازه ایجاد شده ایجاد کنید –

  • به کنسول Firebase بروید.
  • پروژه تازه ایجاد شده را باز کنید.
  • روی گزینه Database در منوی سمت چپ کلیک کنید.
  • گزینه ایجاد پایگاه داده را کلیک کنید.
  • در حالت آزمایشی شروع و سپس فعال کردن را کلیک کنید.
  • روی افزودن مجموعه کلیک کنید. محصول را به عنوان نام مجموعه وارد کرده و سپس روی Next کلیک کنید.
  • اطلاعات نمونه محصول را همانطور که در تصویر نشان داده شده است در اینجا وارد کنید

 

Sample Product Information

 

با استفاده از گزینه های افزودن سند، اطلاعات اضافی محصول را اضافه کنید.

فایل main.dart را باز کرده و فایل افزونه Cloud Firestore را وارد کرده و http بسته را حذف کنید.

import 'package:cloud_firestore/cloud_firestore.dart';

تجزیه محصولات را حذف کرده و واکشی محصولات را برای به دست آوردن محصولات از Cloud Firestore به جای 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()); 
               }
            }, 
         ), 
      )
   ); 
}

 

در اینجا، ما اطلاعات محصول را به صورت List <DocumentSnapshot> دریافت کرده ایم. از آنجا که ویجت ما ، ProductBoxList با اسناد سازگار نیست، ما اسناد را به نوع <List <Product> تبدیل کرده و بیشتر استفاده کردیم.

در آخر، برنامه را اجرا کنید و نتیجه را ببینید. از آنجا که، ما از اطلاعات محصول مشابه برنامه SQLite استفاده کرده ایم و فقط محیط ذخیره سازی را تغییر داده ایم، برنامه به دست آمده با برنامه کاربردی SQLite یکسان به نظر می رسد.

منبع.

لیست جلسات قبل آموزش برنامه نویسی فلاتر

  1. معرفی برنامه نویسی فلاتر
  2. آموزش نصب فلاتر
  3. اصول ایجاد یک برنامه فلاتر در Android Studio
  4. معماری فریم ورک برنامه نویسی فلاتر
  5. مقدمه ای بر برنامه نویسی دارت
  6. مقدمه ای بر ویجت ها در برنامه نویسی فلاتر
  7. آموزش طرح بندی در برنامه نویسی فلاتر 
  8. ژست های حرکتی در برنامه نویسی فلاتر 
  9. مدیریت State در برنامه نویسی فلاتر
  10. آموزش انیمیشن در برنامه نویسی فلاتر
  11. آموزش نوشتن کد خاص اندروید در برنامه نویسی فلاتر
  12. آموزش نوشتن کد مخصوص IOS در برنامه نویسی فلاتر
  13. مقدمه ای بر پکیج ها در برنامه نویسی فلاتر 
0
برچسب ها :
نویسنده مطلب erfan molaei

دیدگاه شما

بدون دیدگاه