Episode ini membuat data kalian bertahan: local storage dengan shared_preferences dan file I/O, database lokal SQLite dengan sqflite dan Drift, caching strategies dan offline support, serta secure storage untuk menyimpan token dan secret dengan aman.

Data yang hilang saat aplikasi ditutup adalah pengalaman buruk. Episode 9 mengajarkan cara menyimpan data secara persisten: preferensi ringan dengan shared_preferences, file I/O untuk data biner, database relasional SQLite lewat sqflite dan Drift, strategi caching untuk offline support, serta penyimpanan token dan secret dengan flutter_secure_storage.
Mulai dengan menambahkan package dasar:
flutter pub add shared_preferences path_providerflutter pub add shared_preferences path_provider memasang dua package sekaligus. shared_preferences menyimpan pasangan key-value sederhana, path_provider menyediakan direktori file yang valid per platform.
Cocok untuk setting, token kecil, dan flag UI:
final prefs = await SharedPreferences.getInstance();
await prefs.setString('nama_pengguna', 'Arman');
final nama = prefs.getString('nama_pengguna') ?? 'anonim';SharedPreferences.getInstance() memberi instance global. setString menulis dan getString membaca nilai; gunakan setInt, setBool, dan setStringList untuk tipe lain. Simpan hanya data kecil di sini — bukan struktur besar.
Untuk dokumen, log, atau data biner, tulis ke file:
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/catatan.txt');
await file.writeAsString('Isi catatan');
final isi = await file.readAsString();getApplicationDocumentsDirectory() mengembalikan direktori dokumen aplikasi yang valid di semua platform. Path dibuat dengan '${dir.path}/catatan.txt' lalu ditulis dan dibaca via File.
Ketika data perlu query, relasi, dan transaksi, pakai SQLite:
flutter pub add sqflite pathContoh pembuatan tabel sederhana:
final db = await openDatabase(
join(await getDatabasesPath(), 'app.db'),
version: 1,
onCreate: (db, version) async {
await db.execute(
'CREATE TABLE tasks(id INTEGER PRIMARY KEY, '
'title TEXT NOT NULL)',
);
},
);openDatabase membuka atau membuat database; onCreate menjalankan skema saat database pertama dibuat. Perhatikan bahwa path.join memakai package path untuk menyusun path yang benar lintas platform.
Drift (dulu Moor) menggantikan SQL mentah dengan query yang diperiksa kompilator. Keuntungan utamanya: kesalahan query terdeteksi saat build, bukan saat runtime. Untuk aplikasi dengan skema kompleks, Drift layak dipertimbangkan.
Simpan respons API ke storage dan tampilkan saat offline:
Future<void> simpanCache(String key, String data) async {
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/cache_$key.json');
await file.writeAsString(data);
}
Future<String?> bacaCache(String key) async {
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/cache_$key.json');
if (await file.exists()) {
return file.readAsString();
}
return null;
}Pola simpanCache dan bacaCache membuat aplikasi menampilkan data terakhir yang diketahui saat jaringan mati, lalu menyegarkan saat kembali online. Untuk cache HTTP yang lebih matang, package cached_network_image menangani gambar, dan hive menawarkan cache object berbasis key-value.
shared_preferences.cached_network_image.Pilih media sesuai bentuk data — menyimpan segalanya di satu tempat hanya akan memperlambat aplikasi.
Token akses dan secret tidak boleh disimpan sebagai teks biasa:
flutter pub add flutter_secure_storageflutter_secure_storage memakai keystore Android dan Keychain iOS — token disimpan terenkripsi:
const storage = FlutterSecureStorage();
await storage.write(key: 'access_token', value: token);
final tersimpan = await storage.read(key: 'access_token');storage.write dan storage.read memakai keamanan platform. Jangan pernah menyimpan token di shared_preferences atau hardcode di kode — keduanya mudah dibaca dari device.
Simpan hanya yang wajib di secure storage; simpan preferensi non-sensitif di shared_preferences. Untuk secret yang perlu disinkronkan antar platform atau di-handle backend, pertimbangkan keystore tingkat sistem atau secret manager di sisi server — topik yang akan kita sentuh di episode 14 dan 19.
Inti yang harus dibawa pulang:
shared_preferences untuk setting ringan; path_provider untuk file I/O.sqflite untuk data relasional; Drift sebagai alternatif type-safe.flutter_secure_storage.Di episode 10 selanjutnya kita membahas advanced state management — perbandingan pattern Provider, Riverpod, Bloc, GetX, dan MobX, reactive state flow dan dependency injection, pengelolaan state kompleks dan modularization, serta cara memilih arsitektur sesuai ukuran aplikasi. Ini titik balik dari aplikasi kecil ke skala menengah.