จัดเก็บการตั้งค่าและข้อมูลขนาดเบาอย่างถาวรด้วย shared_preferences พร้อมรู้ถึงข้อจำกัดด้านความปลอดภัยและปริมาณของมัน
เปิดบทเรียนนี้ใน Kodokonshared_preferences คือที่เก็บข้อมูลแบบคีย์/ค่า (key/value) ที่อาศัยกลไกเนทีฟ (SharedPreferences บน Android, UserDefaults บน iOS) จุดที่มันเหมาะที่สุดคือ ข้อมูลขนาดเล็ก เช่น ธีมที่เลือก การเห็นหน้าจอแนะนำการใช้งานแล้ว หรือแท็บที่ใช้งานล่าสุด นอกเหนือจากนั้น ให้เปลี่ยนเครื่องมือ ใช้ฐานข้อมูล sqflite หรือ drift สำหรับข้อมูลขนาดใหญ่หรือข้อมูลที่ต้องคิวรี และใช้ flutter_secure_storage สำหรับอะไรก็ตามที่ละเอียดอ่อน ไฟล์นี้ถูกโหลดเข้าหน่วยความจำทั้งหมด มันไม่ได้ถูกเข้ารหัสและไม่ได้ถูกสร้างมาเพื่อให้ขยายใหญ่ขึ้น
flutter pub add shared_preferencesgetInstance() เป็นแบบอะซิงโครนัสในการเรียกครั้งแรก (อ่านไฟล์) จากนั้นจะคืนอินสแตนซ์ที่แคชไว้ การเรียก get* ครั้งต่อ ๆ มาจึงเป็น แบบซิงโครนัส โดยดึงจากหน่วยความจำ ส่วนการเรียก set* นั้นเขียนลงดิสก์แบบอะซิงโครนัส ในทางปฏิบัติ อย่ากระจายสตริงคีย์ไปทั่วทั้งแอปพลิเคชัน จงรวมพวกมันไว้ที่ศูนย์กลางในตัวห่อหุ้ม (wrapper) ที่มีชนิดชัดเจน ฉีดเข้าไปได้ และทดสอบได้
import 'package:shared_preferences/shared_preferences.dart';
class SettingsStore {
SettingsStore(this._prefs);
static const _darkModeKey = 'settings.darkMode';
final SharedPreferences _prefs;
static Future<SettingsStore> load() async {
final prefs = await SharedPreferences.getInstance();
return SettingsStore(prefs);
}
bool get darkMode =>
_prefs.getBool(_darkModeKey) ?? false;
Future<void> setDarkMode(bool value) =>
_prefs.setBool(_darkModeKey, value);
}API นี้เก็บได้เฉพาะชนิดข้อมูลพื้นฐานเท่านั้น ได้แก่ bool, int, double, String และ List<String> สำหรับอ็อบเจกต์ที่มีโครงสร้าง ให้ทำให้มันเป็นอนุกรมเป็น JSON โดย toJson/fromJson ของคุณจากบทเรียนแรกกลับมามีประโยชน์อีกครั้งตรงนี้ ข้อแลกเปลี่ยนที่ยอมรับได้คือ การบันทึกแต่ละครั้งจะเขียนค่าทั้งหมดทับใหม่ และไม่สามารถคิวรีได้ เหมาะอย่างยิ่งสำหรับฉบับร่าง แต่ไม่เหมาะกับประวัติ
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class Draft {
const Draft({required this.title, required this.body});
factory Draft.fromJson(Map<String, dynamic> json) =>
Draft(
title: json['title'] as String,
body: json['body'] as String,
);
final String title;
final String body;
Map<String, dynamic> toJson() =>
{'title': title, 'body': body};
}
Future<void> saveDraft(Draft draft) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('draft', jsonEncode(draft));
}
Future<Draft?> loadDraft() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString('draft');
if (raw == null) return null;
return Draft.fromJson(
jsonDecode(raw) as Map<String, dynamic>,
);
}shared_preferences?getInstance() ครั้งแรก การอ่านด้วย get* มีพฤติกรรมอย่างไร?Future ที่คุณต้อง await ทุกครั้งDraft ที่มีโครงสร้างได้อย่างไร?jsonEncode แล้วเก็บมันผ่าน setStringprefs.setObject('draft', draft) ที่ออกแบบมาเพื่อการนี้setStringList