เนื้อหาตอนต่อไปนี้จะมาแนะนำ การบันทึกข้อมูลไว้ใน 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 กรณีที่ออนไลน์อยู่ มาเก็บ
บันทึกในฐานข้อมูล เมื่อออฟไลน์ก็ใช้ข้อมูลในฐานข้อมูลที่เครื่อง แบบนี้เป็นต้น
เนื้อหาตอนหน้าเป็นอะไร รอติดตาม