ด้วยสํานึกในพระมหากรุณาธิคุณสมเด็จพระนางเจ้าสิริกิติ์เป็นล้นพ้นอันหาที่สุดมิได้
ด้วยสํานึกในพระมหากรุณาธิคุณสมเด็จพระนางเจ้าสิริกิติ์เป็นล้นพ้นอันหาที่สุดมิได้


จัดการข้อมูลด้วย SQL Database โดยใช้ Sqflite ใน Flutter

เขียนเมื่อ 4 ปีก่อน โดย Ninenik Narkdee
sqlite database intl flutter ฐานข้อมูล sqflite

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ sqlite database intl flutter ฐานข้อมูล sqflite

ปัจจุบัน นักพัฒนาสามารถ ใช้ ChatGPT | Gemini | Claude | Perplexity | Deepseek ช่วยในการแก้ไขปัญหาต่างๆ ในการเขียนโปรแกรม หรือหาข้อมูลเพิ่มเติมได้ง่ายและสะดวก แนะนำให้ทุกคนใช้งานเพื่อพัฒนาศักยภาพของตัวเอง

ดูแล้ว 16,211 ครั้ง




เนื้อหาตอนต่อไปนี้จะมาแนะนำ การบันทึกข้อมูลไว้ใน app
ในรูปแบบ SQLite database โดยใช้ package ที่ชื่อว่า Sqflite
โดยเนื้อหาจะเน้นไปที่ตัวอย่างโค้ด และการประยุกต์ มากกว่า
การอธิบายทีละส่วน เพราะในการใช้งานมีรายละเอีอดค่อน
ข้างมาก ดังนั้นจึงไว้วิธีแสดงเป็นภาพรวมแทน
 
   *เนื้อหานี้ใช้เนื้อหาต่อเนื่องจากบทความตอนที่แล้ว http://niik.in/1046
 
 

ลำดับสิ่งที่เราจะทำ

    สิ่งที่จะทำเป็นแนวทางการใช้งาน คือ จะสร้างระบบจำลองการเพิ่ม ลบ แก้ไข
เกี่ยวกับรายการหนังสือ ลงในฐานข้อมูล โดยการเพิ่มข้อมูล จะไม่เริ่มไปถึงขึ้นตอน
การสร้างฟอร์มกรอกข้อมูลใดๆ แต่จะใช้ข้อมูลทดสอบ ที่มีรูปแบบถูกต้องสำหรับ
บันทึกลงฐานข้อมูล และเน้นไปที่การทำงานกับฐานข้อมูลในรูปแบบต่างๆ ทั้งการ
เพิ่ม ลบ แก้ไข แสดงรายการทั้งหมด แสดงเฉพาะรายการ ล้างข้อมูลทั้งหมด เป็นต้น
 
    ดูตัวอย่างการทำงานตามรูป
 
 


 
 
    เราเชื่อมไปยังหน้าหนังสือ เริ่มต้นจะยังไม่มีรายการใดๆ จากนั้นกดเพิ่มจำนวน 6 รายการ
จากนั้นกดแสดงรายละเอียดรายการที่ 4 กดปิด จากนั้นกดลบรายการที่ 4 ออกไป ต่อด้วย
แก้ไขรายการที่ 3 สังเกตมีคำว่า new หลังจากแก้ไข และสุดท้ายกด ลบทั้งหมด รายการหาย
ไปจากฐานข้อมูล
 
 
 

เตรียมพร้อมก่อนใช้งาน SQLite database

    เราจะทำการติดตั้ง package ที่ชื่อว่า Sqflite สำหรับจัดการฐานข้อมูล SQLite และติดตั้ง
package ชื่อ intl สำหรับจัดการรูปแบบข้อมูลวันที่
 

     ติดตั้ง Sqflite และ Intl 

     เพิ่มไปในส่วนของไฟล์ pubspec.yaml 
 
dependencies:
  sqflite: ^2.3.3+1
  intl: ^0.19.0
 
    การ import ไปใช้งาน
 
// สำหรับ sqflite
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

// สำหรับ intl
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';
 
    
    ไฟล์ที่เกี่ยวข้อง
    เราจะมีไฟล์ที่เกี่ยวข้องอยู่แค่ 3 ไฟล์ ดังนี้
 
    - lib > screen > book.dart
    - lib > models > book_model.dart
    - lib > db > book_db.dart
 
    โครงสร้างและ path ของไฟล์ตามรูปแบบด้านบน ไฟล์ book.dart เราจะใช้สำหรับจำลองการทำงาน
หลังจากเตรียมส่วนของการทำงานกับฐานข้อมูล และส่วนของข้อมูลไปแล้ว
    ไฟล์ book_db.dart จะเป็นไฟล์ที่รวมเกี่ยวกับฐานข้อมูลหนังสือทั้งหมด เป็นรูปแบบคำสั่งที่รองรับการ
เชื่อมต่อฐานข้อมูล สร้างตาราง เพิ่ม ลบ แก้ไข ข้อมูลในตาราง จะอยู่ในไฟล์นี้ เวลาเอาไปปรับใช้ ก็แก้ไข
เฉพาะส่วนที่ต้องการได้ 
    ไฟล์ book_model.dart เป็นไฟล์ที่รวมการกำหนดลักษณะของข้อมูล รวมถึงฟิลด์ข้อมูลในตารางที่จะใช้
ร่วมกับไฟล์ book_db.dart 
 
    จะเขียนคำอธิบายทั้งหมดไว้ในแต่ละไฟล์ 
 
 

    การเตรียมข้อมูล Data Model

 
    ไฟล์ book_model.dart
 
// กำหนดชื่อตารางไว้ในตัวแปร
final String tableBooks = 'books';

// กำหนดฟิลด์ข้อมูลของตาราง
class BookFields {
  // สร้างเป็นลิสรายการสำหรับคอลัมน์ฟิลด์
  static final List<String> values = [
    id, book_id, title, price, in_stock, num_pages, publication_date
  ];

  // กำหนดแต่ละฟิลด์ของตาราง ต้องเป็น String ทั้งหมด
  static final String id = '_id'; // ตัวแรกต้องเป็น _id ส่วนอื่นใช้ชื่อะไรก็ได้
  static final String book_id = 'book_id';
  static final String title = 'title';
  static final String price = 'price';
  static final String in_stock = 'in_stock';
  static final String num_pages = 'num_pages';
  static final String publication_date = 'publication_date';
}

// ส่วนของ Data Model ของหนังสือ
class Book {
  final int? id; // จะใช้ค่าจากที่ gen ในฐานข้อมูล
  final int book_id; 
  final String title;
  final double price;
  final bool in_stock;
  final int num_pages;
  final DateTime publication_date;

  // constructor
  const Book({
    this.id,
    required this.book_id,
    required this.title,
    required this.price,
    required this.in_stock,
    required this.num_pages,
    required this.publication_date,
  });

  // ฟังก์ชั่นสำหรับ สร้างข้อมูลใหม่ โดยรองรับแก้ไขเฉพาะฟิลด์ที่ต้องการ
  Book copy({
   int? id,
   int? book_id,
   String? title,
   double? price,
   bool? in_stock,
   int? num_pages,
   DateTime? publication_date,
  }) =>
    Book(
      id: id ?? this.id, 
      book_id: book_id ?? this.book_id,
      title: title ?? this.title,
      price: price ?? this.price,
      in_stock: in_stock ?? this.in_stock,
      num_pages: num_pages ?? this.num_pages,
      publication_date: publication_date ?? this.publication_date,
    );

  // สำหรับแปลงข้อมูลจาก Json เป็น Book object
  static Book fromJson(Map<String, Object?> json) =>  
    Book(
      id: json[BookFields.id] as int?,
      book_id: json[BookFields.book_id] as int,
      title: json[BookFields.title] as String,
      price: double.parse(json[BookFields.price] as String),
      in_stock: json[BookFields.in_stock] == 1,
      num_pages: json[BookFields.num_pages] as int,
      publication_date: DateTime.parse(json[BookFields.publication_date] as String),
    );

  // สำหรับแปลง Book object เป็น Json บันทึกลงฐานข้อมูล
  Map<String, Object?> toJson() => {
    BookFields.id: id,
    BookFields.book_id: book_id,    
    BookFields.title: title,
    BookFields.price: price,
    BookFields.in_stock: in_stock ? 1 : 0,
    BookFields.num_pages: num_pages,
    BookFields.publication_date: publication_date.toIso8601String(),
  };


}
 
    สังเกตการแปลงค่า DateTime , Boolean และ Double หากนำไปประยุกต์ใช้งาน ให้ใช้แนวทาง
ตามโค้ดตัวอย่าง ตัวอย่างเช่น boolean พอแปลงเป็นข้อมูล json จะไม่มีรูปแบบข้อมูลนี้ ดังนั้นจึง
ใช้เป็น 1 กับ 0  เช่นกับกับของวันที่ ก็แปลงเป็น string
 
BookFields.in_stock: in_stock ? 1 : 0,
BookFields.publication_date: publication_date.toIso8601String(),
 
    และเวลาแปลงกลับมาจาก json เป็น object ก็ต้องแปลงเป็นชนิดข้อมูลที่กำหนดด้วย
 
price: double.parse(json[BookFields.price] as String), // แปลงเป็น double
in_stock: json[BookFields.in_stock] == 1, // แปลงกลับเป็น boolean 
num_pages: json[BookFields.num_pages] as int,
publication_date: DateTime.parse(json[BookFields.publication_date] as String),
 
    การกำหนด id ควรกำหนดสองส่วน คือเพิ่มของ id ที่เป็นค่าจากฐานข้อมูลที่จะสร้างอัตโนมัติ
กับ id ของรายการนั้น เช่นในตัวอย่าง ก็จะมี id กับ book_id 
 
    รูปแบบการกำหนดของไฟล์ข้างต้น เวลานำไปประยุกต๋ก็แก้ไข และปรับให้เหมือนกับรูปแบบข้างต้น
มีส่วนต่างๆ ให้ครบถ้วน
 
 

    การใช้งาน Sqflite จัดการฐานข้อมูล

 
    ไฟล์ book_db.dart
 
import 'dart:async';

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

import '../models/book_model.dart';

// สร้าง class จัดการข้อมูล
class BooksDatabase {
  // กำหนดตัวแปรสำหรับอ้างอิงฐานข้อมูล
  static final BooksDatabase instance = BooksDatabase._init();

  // กำหนดตัวแปรฐานข้อมูล
  static Database? _database;

  BooksDatabase._init();

  Future<Database> get database async {
    // ถ้ามีฐานข้อมูลนี้แล้วคืนค่า 
    if (_database != null) return _database!;
    // ถ้ายังไม่มี สร้างฐานข้อมูล กำหนดชื่อ นามสกุล .db
    _database = await _initDB('books.db');
    // คืนค่าฐานข้อมูล
    return _database!;
  }

  // ฟังก์ชั่นสร้างฐานข้อมูล รับชื่อไฟล์ที่กำหนดเข้ามา
  Future<Database> _initDB(String filePath) async {
    // หาตำแหน่งที่จะจัดเก็บในระบบ ที่เตรียมไว้ให้
    final dbPath = await getDatabasesPath();
    // ต่อกับชื่อที่ส่งมา จะเป็น path เต็มของไฟล์
    final path = join(dbPath, filePath);
    // สร้างฐานข้อมูล และเปิดใช้งาน หากมีการแก้ไข ให้เปลี่ยนเลขเวอร์ชั่น เพิ่มขึ้นไปเรื่อยๆ
    return await openDatabase(path, version: 1, onCreate: _createDB);

  }

  // สร้างตาราง
   Future _createDB(Database db, int version) async {
     // รูปแบบข้อมูล sqlite ที่รองรับ
     final idType = 'INTEGER PRIMARY KEY AUTOINCREMENT';
     final textType = 'TEXT NOT NULL';
     final boolType = 'BOOLEAN NOT NULL';
     final integerType = 'INTEGER NOT NULL';

    // ทำคำสั่งสร้างตาราง
     await db.execute('''
CREATE TABLE $tableBooks (
  ${BookFields.id} $idType,
  ${BookFields.book_id} $integerType,
  ${BookFields.title} $textType,
  ${BookFields.price} $textType,
  ${BookFields.in_stock} $boolType,
  ${BookFields.num_pages} $integerType,
  ${BookFields.publication_date} $textType
)
''');
   } 

  // คำสั่งสำหรับเพิ่มข้อมูลใหม่ คืนค่าเป็น book object ที่เพิ่มไป
  Future<Book> create(Book book) async {
    final db = await instance.database; // อ้างอิงฐานข้อมูล

    final id = await db.insert(tableBooks, book.toJson());
    return book.copy(id: id);
  }

  // คำสั่งสำหรับแสดงข้อมูลหนังสือตามค่า id ที่ส่งมา
  Future<Book> readBook(int id) async {
    final db = await instance.database; // อ้างอิงฐานข้อมูล

    // ทำคำสั่งคิวรี่ข้อมูลตามเงื่อนไข 
    final maps = await db.query(
      tableBooks,
      columns: BookFields.values,
      where: '${BookFields.id} = ?',
      whereArgs: [id],
    );

    // ถ้ามีข้อมูล แสดงข้อมูลกลับออกไป
    if (maps.isNotEmpty) {
      return Book.fromJson(maps.first);
    } else { // ถ้าไม่มีแสดง error 
      throw Exception('ID $id not found');
    }
  }  

  // คำสั่งแสดงรายการหนึงสือทั้งหมด ต้องส่งกลับเป็น List
  Future<List<Book>> readAllBook() async {
    final db = await instance.database; // อ้างอิงฐานข้อมูล

    // กำหนดเงื่อนไขต่างๆ รองรับเงื่อนไขและรูปแบบของคำสั่ง sql ตัวอย่าง
    // ใช้แค่การจัดเรียงข้อมูล
    final orderBy = '${BookFields.id} DESC';
    final result = await db.query(tableBooks, orderBy: orderBy);

    // ข้อมูลในฐานข้อมูลปกติเป็น json string data เวลาสั่งค่ากลับต้องทำการ
    // แปลงข้อมูล จาก json ไปเป็น object กรณีแสดงหลายรายการก็ทำเป็น List
    return result.map((json) => Book.fromJson(json)).toList();
  }  

  // คำสังสำหรับอัพเดทข้อมููล ส่ง book object ที่จะอัพเดทเข้ามา
  Future<int> update(Book book) async {
    final db = await instance.database; // อ้างอิงฐานข้อมูล

    // คืนค่าเป็นตัวเลขจำนวนรายการที่มีการเปลี่ยนแปลง
    return db.update(
      tableBooks, 
      book.toJson(),
      where: '${BookFields.id} = ?',
      whereArgs: [book.id],      
    );

  }

  // คำสั่งสำหรับลบข้อมล รับค่า id ที่จะลบ
  Future<int> delete(int id) async {
    final db = await instance.database; // อ้างอิงฐานข้อมูล

    // คืนค่าเป็นตัวเลขจำนวนรายการที่มีการเปลี่ยนแปลง
    return db.delete(
      tableBooks, 
      where: '${BookFields.id} = ?',
      whereArgs: [id],      
    );

  }

  // คำสั่งสำหรับลบข้อมูลทั้งหมด
  Future<int> deleteAll() async {
    final db = await instance.database; // อ้างอิงฐานข้อมูล
    // คืนค่าเป็นตัวเลขจำนวนรายการที่มีการเปลี่ยนแปลง
    return db.delete(
      tableBooks,
    );

  }  

  // คำสั่งสำหรับปิดฐานข้อมูล เท่าที่ลองใช้ เราไม่ควรปิด หรือใช้คำสั่งนี้
  // เหมือนจะเป็น bug เพราะถ้าปิดฐานข้อมูล จะอ้างอิงไม่ค่อยได้ ในตัวอย่าง
  // จะไม่ปิดหรือใช้คำสั่งนี้
   Future close() async {
     final db = await instance.database; // อ้างอิงฐานข้อมูล

     db.close();
   }

}
 
    ในไฟล์นี้ จะเป็นการทำงานของฝั่งฐานข้อมูลทั้งหมด สามารถปรับประยุกต์ จากตัวอย่างได้เลย
เพราะรองรับการเพิ่ม ลบ แก้ไขรายการ ในกรณีแสดงทั้งหมด สามารถเลือกกำหนดจำนวน เงื่อนไข
จัดกลุ่ม เหล่านี้เพิ่มเติมได้ เช่น
 
final orderBy = '${BookFields.id} DESC';
final result = await db.query(tableBooks, 
    orderBy: orderBy,
    where: 'xxxx', // กำหนด string คำสั่งตามต้องการ
    groupBy: 'xxxx', // กำหนด string คำสั่งตามต้องการ
    offset: 0,
    limit: 10,
);
 
 
 

การประยุกต์ใช้งาน Sqflite

     มาถึงส่วนของการประยุกต์ใช้งาน หรือการนำ คำสั่งที่จัดการกับฐานข้อมูลมาใช้งานหน้า app ที่ต้องการ
ในที่นี้เราใช้ในไฟล์ชื่อ book.dart 
 
    ไฟล์ book.dart
 
import 'dart:async';
 
import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';
 
import '../db/book_db.dart';
import '../models/book_model.dart';
   
class Books extends StatefulWidget {
    static const routeName = '/book';
  
    const Books({Key? key}) : super(key: key);
   
    @override
    State<StatefulWidget> createState() {
        return _BooksState();
    }
}
   
class _BooksState extends State<Books> {
    late BooksDatabase _db; // อ้างอิงฐานข้อมูล
    late Future<List<Book>> books; // ลิสรายการหนังสือ
    int i = 0; // จำลองตัวเลขการเพิ่่มจำนวน
    late DateFormat dateFormat; // รูปแบบการจัดการวันที่และเวลา
 
    @override
    void initState() {
      // กำหนดรูปแบบการจัดการวันที่และเวลา มีเพิ่มเติมเล็กน้อยในในท้ายบทความ
      Intl.defaultLocale = 'th';
      initializeDateFormatting();
      dateFormat = DateFormat.yMMMMEEEEd('th');
 
      // อ้างอิงฐานข้อมูล
      _db = BooksDatabase.instance;
      books = _db.readAllBook(); // แสดงรายการหนังสือ
      super.initState();
    }
 
    // คำสั่งลบรายการทั้งหมด
    Future<void> clearBook() async {
      await _db.deleteAll(); // ทำคำสั่งลบข้อมูลทั้งหมด
      setState(() {
        books = _db.readAllBook(); // แสดงรายการหนังสือ
      });      
    }
 
    // คำสั่งลบเฉพาะรายการที่กำหนดด้วย id ที่ต้องการ
    Future<void> deleteBook(int id) async {
      await _db.delete(id); // ทำคำสั่งลบข้มูลตามเงื่อนไข id
      setState(() {
        books = _db.readAllBook(); // แสดงรายการหนังสือ
      });    
    }
 
    // จำลองทำคำสั่งแก้ไขรายการ
    Future<void> editBook(Book book) async {
      // เลื่อกเปลี่ยนเฉพาะส่วนที่ต้องการ โดยใช้คำสั่ง copy
      book = book.copy(
        title: book.title+' new ',
        price: 30.00,
        in_stock: true,
        num_pages: 300,
        publication_date: DateTime.now()
      );      
      await _db.update(book); // ทำคำสั่งอัพเดทข้อมูล
      setState(() {
        books = _db.readAllBook(); // แสดงรายการหนังสือ
      });    
    }    
 
    // จำลองทำคำสั่งเพิ่มข้อมูลใหม่
    Future<void> newBook() async {
      i++;
      Book book = Book(
        book_id: i,
        title: 'Book title $i',
        price: 20.00,
        in_stock: true,
        num_pages: 200,
        publication_date: DateTime.now()
      );
      await _db.create(book); // ทำคำสั่งเพิ่มข้อมูลใหม่
      setState(() {
        books = _db.readAllBook(); // แสดงรายการหนังสือ
      });
    }
 
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text('Book'),
                actions: <Widget>[ // 
                  IconButton(
                    onPressed: () => clearBook(), // ปุ่มลบข้อมูลทั้งหมด
                    icon: const Icon(Icons.clear_all),
                  ),
                ],
            ),
            body: Center(
              child: FutureBuilder<List<Book>>( // ชนิดของข้อมูล
                future: books, // ข้อมูล Future
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                      return Column(
                          children: [
                            Expanded( // ส่วนของลิสรายการ
                                child: snapshot.data!.isNotEmpty // กำหนดเงื่อนไขตรงนี้
                                ? ListView.separated( // กรณีมีรายการ แสดงปกติหนด controller ที่จะใช้งานร่วม
                                        itemCount: snapshot.data!.length,
                                        itemBuilder: (context, index) {
                                          Book book = snapshot.data![index];
 
                                          Widget card; // สร้างเป็นตัวแปร
                                          card = Card(
                                            margin: const EdgeInsets.all(5.0), // การเยื้องขอบ
                                            child: Column(
                                              children: [
                                                ListTile(
                                                  leading: IconButton(
                                                    onPressed: () => editBook(book), // จำลองแก้ไขข้อมูล
                                                    icon: const Icon(Icons.edit),
                                                  ),
                                                  title: Text(book.title),
                                                  subtitle: Text('Date: ${dateFormat.format(book.publication_date)}'),
                                                  trailing: IconButton(
                                                    onPressed: () => deleteBook(book.id!), // ลบข้อมูล
                                                    icon: const Icon(Icons.delete),
                                                  ),
                                                  onTap: (){
                                                     _viewDetail(book.id!); // กดเลือกรายการให้แสดงรายละเอียด                                           
                                                  },
                                                ),
                                              ],
                                            )
                                          );
                                          return card;
                                        },
                                        separatorBuilder: (BuildContext context, int index) => const SizedBox(),
                                )
                                : const Center(child: Text('No items')), // กรณีไม่มีรายการ
                            ),
                          ],
                        );
                  } else if (snapshot.hasError) { // กรณี error
                    return Text('${snapshot.error}');
                  }
                  // กรณีสถานะเป็น waiting ยังไม่มีข้อมูล แสดงตัว loading
                 return const RefreshProgressIndicator();
                },
              ),  
            ),  
            floatingActionButton: FloatingActionButton(
              onPressed: () => newBook(),
              child: const Icon(Icons.add),
            ),
        );
    }
 
    // สร้างฟังก์ชั่นจำลองการแสดงรายละเอียดข้อมูล
    Future<Widget?> _viewDetail(int id) async {
      Future<Book> book = _db.readBook(id); // ดึงข้อมูลจากฐานข้อมูลมาแสดง
      showModalBottomSheet(
        context: context,
        builder: (BuildContext context){
            return FutureBuilder<Book>(
              future: book,
              builder: (context,snapshot){
                if (snapshot.hasData) {
                  var book = snapshot.data!;
                  return Container(
                    width: MediaQuery.of(context).size.width,
                    height: 200,
                    padding: const EdgeInsets.all(10.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text('ID: ${book.id}'),
                        SizedBox(height: 5,),
                        Text('ชื่อหนังสือ: ${book.title}'),
                        SizedBox(height: 5,),
                        Text('รหัส: ${book.book_id}'),
                        SizedBox(height: 5,),
                        Text('ราคา: ${book.price}'),
                        SizedBox(height: 5,),
                        Text('จำนวนหน้า: ${book.num_pages}'),
                        SizedBox(height: 5,),
                        Text('มีในคลัง: ${ book.in_stock ? 'มี' : 'ไม่มี'}'),
                        SizedBox(height: 5,),
                        Text('วันที่: ${dateFormat.format(book.publication_date)}'),
                      ],
                    ),
                  );
                } else if (snapshot.hasError) { // กรณี error
                  return Text('${snapshot.error}');
                }
                return const RefreshProgressIndicator();
              }
            );
        }
      );
      return null;
    }
 
}
 
    เพิ่มปุ่มลิ้งค์มาหน้า book ในไฟล์ about.dart
มีสองส่วนคือ import book.dart

import './book.dart'; 


และ ส่วนของการกำหนดปุ่ม

ElevatedButton(
  onPressed: () {
	/* Navigator.pushNamed(
		context,
		Books.routeName
	); */
	Navigator.push(
	  context, 
	  MaterialPageRoute(builder: (context) => Books()),
	);                              
  },
  child: Text('Go to Book'),
),   
 
    ในตัวอย่าง เรามีการใช้งานฐานข้อมูล จากไฟล์ book_db.dart ที่มีคำสั่งต่างๆ ที่เรากำหนดไว้แล้ว
โดยกำหนดตัวแปรชื่อ _db = BooksDatabase.instance; สำหรับอ้างอิงฐานข้อมูล สำหรับขอมูลที่ได้
จากการแสดงรายการทั้งหมด หรือแสดงบางรายการตาม id ที่กำหนด จะเป็นข้อมูล Future เวลาแสดง
เราจึงใช้ FutureBuilder มาใช้งานร่วมด้วย
    เมื่อเริ่มทำงาน เราจะทำการไปอ่านข้อมูลจากฐานข้อมูล ว่ามีรายการหนังสืออยู่หรือไม่ ถ้ามีก็คืนค่า
กลับมาใช้งาน ถ้าไม่มีก็แสดงข้อความ 'No items'
    เราจำลองเมื่อกดปุ่มเครื่องหมายบวก + ก็ให้ทำการเพิ่มข้อมูลลงในฐานข้อมูล หลังจากเพิ่มก็อัพเดท
รายการข้อมูล ก็จะเห็นว่ามีรายการใหม่เพิ่มเข้ามาด้านบน
    เมื่อกดที่รายการใดๆ ก็จะไปดึงข้อมูลจากฐานข้อมูล ของรายการนั้นๆ มาแสดง จริงๆ ถ้าข้อมูลใน
snapshot มีข้อมูลทั้งหมดแล้ว เราไม่จำเป็นต้องไปดึงจากฐานข้อมูลก็ได้ สามารถส่งค่ามาแสดงได้เลย
แต่ในที่นี้ เราจำลองสมมติว่า ต้องการไปดึงข้อมูลทั้งหมดจากฐานข้อมูลมาแสดงแทนการส่งค่า
    เราสามารถลบราายการทั้งหมด โดยคลิกที่ปุ่ม action มุมบนขวา
    การลบ และแก้ไขแต่ละรายการ สามารถกดที่ไอคอน ด้านหน้า และด้านหลังแต่ละรายการตามลำดับ
 
 

การจัดรูปแบบวันที่ด้วย intl package

    เราสามารถจัดรูปแบบการแสดงข้อมูลวันที่หรือ DateTime ด้วย package ชื่อ intl ที่ได้ติดตั้งไปตอนต้น
ซึ่งรองรับการกำหนดและแสดงเป็นภาษาไทย มีรูปแบบการใช้งานไม่ยุ่งยาก
 
    ตัวอย่างการกำหนดรูปแบบโดยใช้ค่าคงที่
 
DateFormat.MMMM('th'),			: พฤศจิกายน 
DateFormat.MMMMd('th'),		  : 6 พฤศจิกายน 
DateFormat.MMMMEEEEd('th'),	: วันเสาร์ที่ 6 พฤศจิกายน 
DateFormat.M('th'),				  : 11 
DateFormat.Md('th'),				: 6/11 
DateFormat.MEd('th'),			  : ส. 6/11 
DateFormat.s('th'),				  : 16 
DateFormat.LLLL('th'),			: พฤศจิกายน 
DateFormat.EEEE('th'),			: วันเสาร์ 
DateFormat.y('th'),				  : 2021 
DateFormat.yMMM('th'),			: พ.ย. 2021 
DateFormat.yMMMd('th'),		  : 6 พ.ย. 2021 
DateFormat.yMMMEd('th'),		: ส. 6 พ.ย. 2021 
DateFormat.yQQQ('th'),			: ไตรมาส 4 2021 
DateFormat.yMMMM('th'),		    : พฤศจิกายน ค.ศ. 2021 
DateFormat.yMMMMEEEEd('th'),	: วันเสาร์ที่ 6 พฤศจิกายน ค.ศ. 2021 
DateFormat.yMMMMd('th'),	    : 6 พฤศจิกายน ค.ศ. 2021 
DateFormat.yM('th'),			: 11/2021 
DateFormat.yMd('th'),			: 6/11/2021 
DateFormat.yMEd('th'),		: ส. 6/11/2021 
DateFormat.yQQQQ('th'),		: ไตรมาส 4 ค.ศ. 2021 
DateFormat.MMM('th'),			: พ.ย.
DateFormat.MMMd('th'),		: 6 พ.ย.
DateFormat.MMMEd('th'),		: ส. 6 พ.ย.
DateFormat.QQQ('th'),			: ไตรมาส 4
DateFormat.LLL('th'),			: พ.ย.
DateFormat.E('th'),				: ส.
DateFormat.d('th'),				: 6
DateFormat.m('th'),				: 52 
DateFormat.ms('th'),			: 52:16 
DateFormat.j('th'),				: 17
DateFormat.H('th'),				: 17
DateFormat.Hm('th'),			: 17:45 น.
DateFormat.Hms('th'),			: 17:45:10
DateFormat.jm('th'),			: 17:49 น.
DateFormat.jms('th'),			: 17:49:25
 
    ตัวอย่างเช่น เรากำหนดเป็น
 
// กำหนดรูปแบบการจัดการวันที่และเวลา มีเพิ่มเติมเล็กน้อยในในท้ายบทความ
Intl.defaultLocale = 'th';
initializeDateFormatting();
dateFormat = DateFormat.yMMMd('th');
 
    ผลลัพธ์ที่ได้
 
 



 
    หรือกรณีเราต้องการรูปแบบที่มีข้อความกำหนดเอง เช่น
 
// กำหนดรูปแบบการจัดการวันที่และเวลา มีเพิ่มเติมเล็กน้อยในในท้ายบทความ
Intl.defaultLocale = 'th';
initializeDateFormatting();
// dateFormat = DateFormat.yMMMd('th');
dateFormat = DateFormat('วันที่ d เดือน MMM ปี y','th');
 
    จะได้เป็น
 
 

 
 
 
    หวังว่าเนื้อหาตอนนี้ จะสามารถเป็นแนวทางนำไปปรับใช้งาน เช่น ต้องการให้ app สามารถทำงาน
ออฟไลน์ได้ โดยบันทึกลงในฐานข้อมูลไว้ และเมื่ออนไลน์หรือเชื่อมต่ออินเตอร์เน็ตก็สามารถ sync ข้อมูล
ขึ้นไปเก็บบน server ได้  หรือจะใช้เก็บข้อมูล cache เช่น ดึงข้อมูลจาก server กรณีที่ออนไลน์อยู่ มาเก็บ
บันทึกในฐานข้อมูล เมื่อออฟไลน์ก็ใช้ข้อมูลในฐานข้อมูลที่เครื่อง แบบนี้เป็นต้น
    เนื้อหาตอนหน้าเป็นอะไร รอติดตาม


   เพิ่มเติมเนื้อหา ครั้งที่ 1 วันที่ 29-07-2024


ดาวน์โหลดโค้ดตัวอย่าง สามารถนำไปประยุกต์ หรือ run ทดสอบได้

http://niik.in/download/flutter/demo_021_29072024_source.rar





อ่านต่อที่บทความ



ทบทวนบทความที่แล้ว









เนื้อหาที่เกี่ยวข้อง






เนื้อหาพิเศษ เฉพาะสำหรับสมาชิก

กรุณาล็อกอิน เพื่ออ่านเนื้อหาบทความ

ยังไม่เป็นสมาชิก

สมาชิกล็อกอิน



( หรือ เข้าใช้งานผ่าน Social Login )




URL สำหรับอ้างอิง








เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ