[TUTORIAL] Cara melakukan Data Persist dengan SQLite dalam Flutter

Assalamu‘alaikum wr. wb.

Hello guys! Jika kita ingin mengembangkan Aplikasi Mobile Flutter, tentunya juga membutuhkan Database agar dapat menyimpan sebuah Data. Kali ini kita akan membuat Tutorial Cara melakukan Data Persist dengan SQLite dalam Flutter.

Data Persist dengan SQLite dalam Flutter

Sumber Referensi : Blog.Logrocket.comGeeksforgeeks.org, dan Medium.Flutterdevs.com

A. Download DB Browser for SQLite

Pertama, kunjungilah terlebih dahulu di Situs Resmi-nya DB Browser for SQLite di sini, dan klik pada bagian "Download" di atas.

Kemudian, klik "Download" untuk mengunduh DB Browser for SQLite.

Jika sudah, bukalah Setup DB Browser for SQLite, dan lakukan Instalasi sampai selesai.

Jika sudah, maka akan seperti ini :

B. Membuat Database SQLite dengan DB Browser

Jika sudah, maka klik pada "New Database" di bagian atas. Namailah Database yang ingin Anda namai, misalnya "mahasiswa".

Setelah itu, buatlah Tabel pada Database yang telah Anda buat tadi. Dan juga isilah nama Field seperti :

  • id : Text (Primary Key)
  • name : Text
  • age : Integer

Jika sudah, maka tampilannya akan seperti ini :


C. Membuat Project Flutter dan menghubungkan ke Database SQLite

Pertama, buatlah Project Flutter seperti biasa. Untuk di Android Studio, namailah Project yang akan kita buat dengan nama "persist_data".

Dan untuk di VS Code, ketiklah Perintah berikut ini :

flutter create persist_data
cd persist_data

Setelah itu, Tambahkan Dependency Package SQLite ke File pubspec.yaml berikut ini :

dependencies:
  flutter:
    sdk: flutter
  sqflite:
  path: any
  uuid:

C. Mendefinisikan Kode Program

Untuk Project kali ini, kita akan membuat Aplikasi Sederhana untuk Mahasiswa. Tapi sebelum itu, inilah Penjabaran dari File Directory dari Project Flutter di bawah ini :

📁 persist_data
├── 📁 lib
   ├── 📁 db_persistence
      ├── DbSqlite.dart
      ├── Mahasiswa.dart
   ├── MahasiswaViewPersistenceUI.dart
   ├── main.dart
├── .gitignore
├── .metadata
├── analysis_options.yaml
├── nama_project_aplikasi.iml
├── pubspec.lock
├── pubspec.yaml
├── README.md

1. Mendefinisikan Model Mahasiswa (mahasiswa)

Mendefinisikan kelas model di mana data perlu disimpan. Kelas model kita memiliki id anggota id, name, age, dan konstruktor yang menginisialisasi anggota data.

[Nama File : Mahasiswa.dart]

class Mahasiswa {
  String id;
  String name;
  int age;

  Mahasiswa({
    required this.id,
    required this.name,
    required this.age,
  });

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'age': age,
    };
  }

  @override
  String toString() {
    return 'Mahasiswa{id: $id, name: $name, age: $age}';
  }
}

2. Mendefinisikan Kelas Database

Di kelas Database kita memiliki semua fungsi yang diimplementasikan di sini, Kelas Database memiliki metode berikut :

a. initDb

  • Metode ini bersifat statis dan berfungsi untuk menginisialisasi database.
  • Menggunakan fungsi getDatabasesPath() dari paket path untuk mendapatkan path database.
  • Menggunakan fungsi openDatabase dari paket sqflite untuk membuka database. Jika database belum ada, maka akan dibuat.
  • Callback onCreate digunakan untuk membuat tabel 'mahasiswas' dengan kolom 'id' (TEXT, PRIMARY KEY), 'name' (TEXT), dan 'age' (INTEGER).

b. insertMahasiswa

  • Menyisipkan objek Mahasiswa baru ke dalam tabel 'mahasiswas'.
  • Menggunakan metode insert yang disediakan oleh sqflite.
  • mahasiswa.toMap() digunakan untuk mengonversi objek Mahasiswa menjadi peta yang mewakili satu baris dalam tabel.

c. mahasiswas

  • Mengambil daftar semua objek Mahasiswa dari tabel 'mahasiswas'.
  • Menggunakan metode query untuk mendapatkan semua baris dari tabel.
  • Hasilnya kemudian dikonversi menjadi daftar objek Mahasiswa.

d. getMahasiswa

  • Mengambil objek Mahasiswa tertentu dari tabel 'mahasiswas' berdasarkan id yang diberikan.
  • Menggunakan metode query dengan klausa WHERE untuk mendapatkan satu baris tertentu.
  • Jika tidak ada baris yang cocok, objek Mahasiswa default dengan nama dan usia dummy akan dikembalikan.

e. updateMahasiswa

  • Memperbarui objek Mahasiswa yang sudah ada di tabel 'mahasiswas'.
  • Menggunakan metode update yang disediakan oleh sqflite.
  • mahasiswa.toMap() digunakan untuk mengonversi objek Mahasiswa menjadi peta untuk proses pembaruan.

f. deleteMahasiswa

  • Menghapus objek Mahasiswa tertentu dari tabel 'mahasiswas' berdasarkan id yang diberikan.
  • Menggunakan metode delete dengan klausa WHERE untuk menghapus satu baris tertentu.

Secara keseluruhan, kelas DbService menyediakan metode-metode untuk melakukan operasi CRUD (Create, Read, Update, Delete) pada database SQLite untuk objek Mahasiswa. Ini membungkus operasi-operasi database dan memberikan API yang bersih untuk berinteraksi dengan database.

[Nama File :  DbSqlite.dart]

import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:uuid/uuid.dart';

import 'Mahasiswa.dart';

void RunLatDB() async {
  WidgetsFlutterBinding.ensureInitialized();
  final dbPath = await getDatabasesPath();
  final database = await openDatabase(
    join(dbPath!, 'mahasiswa_database.db'),
    onCreate: (db, version) {
      return db.execute(
        'CREATE TABLE mahasiswas(id TEXT PRIMARY KEY, name TEXT, age INTEGER)',
      );
    },
    version: 1,
  );
}

class DbService {
  final Database database;

  DbService({required this.database});

  static Future<Database> initDb() async {
    WidgetsFlutterBinding.ensureInitialized();
    final dbPath = await getDatabasesPath();
    final database = await openDatabase(
      join(dbPath!, 'mahasiswa_database.db'),
      onCreate: (db, version) {
        return db.execute(
          'CREATE TABLE mahasiswas(id TEXT PRIMARY KEY, name TEXT, age INTEGER)',
        );
      },
      version: 1,
    );
    return database;
  }

  Future<void> insertMahasiswa(Mahasiswa mahasiswa) async {
    final db = await database;
    await db.insert(
      'mahasiswas',
      mahasiswa.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  Future<List<Mahasiswa>> mahasiswas() async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query('mahasiswas');
    return List.generate(maps.length, (i) {
      return Mahasiswa(
        id: maps[i]['id'],
        name: maps[i]['name'],
        age: maps[i]['age'],
      );
    });
  }

  Future<Mahasiswa> getMahasiswa(String id) async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query(
      'mahasiswas',
      where: 'id = ?',
      whereArgs: [id],
    );
    var mhss = List.generate(maps.length, (i) {
      return Mahasiswa(
        id: maps[i]['id'],
        name: maps[i]['name'],
        age: maps[i]['age'],
      );
    });

    if (mhss.length <= 0) {
      return Mahasiswa(id: id, name: "Dummy", age: 22);
    } else
      return mhss.first;
  }

  Future<void> updateMahasiswa(Mahasiswa mahasiswa) async {
    final db = await database;
    await db.update(
      'mahasiswas',
      mahasiswa.toMap(),
      where: 'id = ?',
      whereArgs: [mahasiswa.id],
    );
  }

  Future<void> deleteMahasiswa(String id) async {
    final db = await database;
    await db.delete(
      'mahasiswas',
      where: 'id = ?',
      whereArgs: [id],
    );
  }
}

3. Mendefinisikan File Utama

Program di atas adalah aplikasi Flutter yang menggunakan SQLite untuk menyimpan dan mengelola data mahasiswa. Mari kita jelaskan beberapa bagian kodenya :

  • MahasiswaViewPersistenceUI : Kelas ini merupakan tampilan utama aplikasi. Membuat objek Scaffold dengan AppBar berisi judul "UI Persistence", Membuat PostToServerCom sebagai badan utama aplikasi.
  • PostToServerCom : Kelas ini merupakan widget stateful. Pada saat inisialisasi (initState), membuka database menggunakan DbService.initDb() dan menginisialisasi dbService, getMahasiswas dipanggil untuk mendapatkan daftar mahasiswa dari database dan menetapkan ke dalam variabel _mahasiswas. Terdapat dua TextEditingController (currentMhsName dan currentMhsUmur) untuk mengontrol input nama dan umur mahasiswa. Menerapkan antarmuka pengguna terdiri dari beberapa elemen, seperti tombol "Update", "Add", dan "X" untuk masing-masing mahasiswa, showMhs mengontrol tampilan antarmuka pengguna, apakah menunjukkan daftar mahasiswa atau antarmuka pengguna untuk mengedit atau menambahkan mahasiswa baru.
  • initState : Dipanggil pada saat pembuatan objek. Di dalamnya, database diinisialisasi dan daftar mahasiswa diambil dari database. Jika tidak ada mahasiswa, satu mahasiswa dummy ditambahkan.
  • dispose : Dipanggil saat objek dihapus. Digunakan untuk menghentikan pengontrol teks.
  • getMahasiswas : Mengambil daftar mahasiswa dari database menggunakan dbService!.mahasiswas(). Jika tidak ada mahasiswa, maka satu mahasiswa dummy ditambahkan ke database dan diambil kembali.
  • build : Membangun tampilan utama aplikasi. Jika showMhs adalah true, maka memanggil metode showMahasiwa untuk menampilkan antarmuka pengguna pengeditan mahasiswa. Jika tidak, mengecek apakah _mahasiswas adalah null atau tidak, dan memanggil showMahasiwas jika tidak null.
  • showMahasiwa : Membuat antarmuka pengguna untuk mengedit atau menambahkan mahasiswa. Menggunakan FutureBuilder untuk menampilkan widget sesuai dengan status future dari _mhs. Menampilkan TextField untuk nama dan umur mahasiswa, serta tombol "Update", "Add", dan "X" untuk mengelola data mahasiswa.
  • showMahasiwas : Membuat daftar mahasiswa yang dapat di-scroll. Setiap mahasiswa ditampilkan sebagai tombol yang menampilkan informasi nama dan umur mahasiswa. Jika salah satu tombol diklik, maka data mahasiswa ditampilkan di antarmuka pengguna pengeditan.

Program ini merupakan contoh sederhana penggunaan SQLite dalam Flutter untuk menyimpan dan mengelola data mahasiswa.

[Nama File : MahasiswaViewPersistenceUI.dart]

import 'dart:async';
import 'package:flutter/material.dart';
import 'db_persistence/DbSqlite.dart';
import 'db_persistence/Mahasiswa.dart';
import 'package:uuid/uuid.dart';

class MahasiswaViewPersistenceUI extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('UI Persistence'),
        ),
        body: Center(
          child: PostToServerCom(),
        ),
      ),
    );
  }
}

class PostToServerCom extends StatefulWidget {
  const PostToServerCom({Key? key}) : super(key: key);

  @override
  _MyAppState createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<PostToServerCom> {
  DbService? dbService;

  Future<Mahasiswa>? _mhs;
  List<Mahasiswa>? _mahasiswas;
  var currentMhsName = TextEditingController();
  var currentMhsUmur = TextEditingController();
  bool showMhs = false;

  @override
  initState() {
    super.initState();

    var db = DbService.initDb();
    dbService = new DbService(database: db);
    getMahasiswas();
  }

  @override
  void dispose() {
    currentMhsName.dispose();
    super.dispose();
  }

  getMahasiswas() async {
    List<Mahasiswa> mahasiswas = await dbService!.mahasiswas();
    if (mahasiswas.length == 0) {
      var uuid = Uuid();
      var id = uuid.v4();
      var mhsNew = new Mahasiswa(id: id.toString(), name: "Nama", age: 33);
      await dbService!.insertMahasiswa(mhsNew);
      mahasiswas = await dbService!.mahasiswas();
    }
    setState(() {
      _mahasiswas = mahasiswas;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Create Data Example',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: showMhs
            ? showMahasiwa()
            : _mahasiswas == null
                ? null
                : showMahasiwas());
  }

  FutureBuilder<Mahasiswa> showMahasiwa() {
    return FutureBuilder<Mahasiswa>(
      future: _mhs,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Container(
            height: 40,
            child: Row(
              children: <Widget>[
                Expanded(
                  child: TextField(
                    controller: currentMhsName,
                  ),
                ),
                SizedBox(width: 20),
                Expanded(
                  child: TextField(
                    controller: currentMhsUmur,
                  ),
                ),
                ElevatedButton(
                  onPressed: () {
                    var mhs = _mahasiswas!
                        .firstWhere((item) => item.id == snapshot.data!.id);
                    setState(() => mhs.name = currentMhsName.text);
                    setState(() => mhs.age = int.parse(currentMhsUmur.text));
                    dbService!.updateMahasiswa(mhs);
                    setState(() {
                      _mahasiswas = _mahasiswas;

                      showMhs = false;
                    });
                  },
                  child: Text("Update"),
                ),
                ElevatedButton(
                  onPressed: () {
                    var uuid = Uuid();
                    var id = uuid.v4();
                    var mhsNew = new Mahasiswa(
                        id: id.toString(),
                        name: currentMhsName.text,
                        age: int.parse(currentMhsUmur.text));
                    dbService!.insertMahasiswa(mhsNew);
                    getMahasiswas();
                    setState(() {
                      showMhs = false;
                      showMhs = false;
                    });
                  },
                  child: Text("Add"),
                ),
                ElevatedButton(
                  onPressed: () {
                    dbService!.deleteMahasiswa(snapshot.data!.id);
                    _mahasiswas!
                        .removeWhere((item) => item.id == snapshot.data!.id);
                    setState(() {
                      _mhs = null;
                      showMhs = false;
                    });
                  },
                  child: Text("X"),
                ),
              ],
            ),
          );
        } else if (snapshot.hasError) {
          return Text('${snapshot.error}');
        }

        return const CircularProgressIndicator();
      },
    );
  }

  ListView showMahasiwas() {
    var viewsMhss = ListView.builder(
        padding: const EdgeInsets.all(8),
        itemCount: _mahasiswas?.length,
        itemBuilder: (BuildContext context, int index) {
          var mhs = _mahasiswas![index];
          var mhsInfo = "Nama:" + mhs.name + ", Umur:" + mhs.age.toString();
          return Container(
            margin: const EdgeInsets.all(2.0),
            height: 50,
            child: ElevatedButton(
              onPressed: () {
                currentMhsName.text = mhs.name;
                currentMhsUmur.text = mhs.age.toString();
                var mhsDB = dbService!.getMahasiswa(mhs.id);
                setState(() {
                  _mhs = mhsDB;
                });
                setState(() {
                  showMhs = true;
                });
              },
              child: Text(mhsInfo),
            ),
          );
        });

    return viewsMhss;
  }
}

4. Menjalankan Program Utama (main.dart)

Jika sudah membuat Program di atas, maka inilah Program Utama dari Dart (main.dart) :

import 'package:flutter/material.dart';
import 'package:persist_data/MahasiswaViewPersistenceUI.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MahasiswaViewPersistenceUI(),
    );
  }
}

Kemudian, Jalankan seperti biasa jika memiliki Emulator Android atau mengoneksikan ke Ponsel Android dengan USB. Dan seharusnya, tampilannya seperti ini :


VIDEO

Inilah Referensi Video untuk Tutorial lainnya yang terkait dengan Cara melakukan Data Persist dengan SQLite dalam Flutter.


Itulah Tutorial Cara melakukan Data Persist dengan SQLite dalam Flutter. Mohon maaf apabila ada sedikit kekurangan, dikarenakan Laptop saya tidak bisa menggunakan Emulator Android, dan juga belum berhasil menghubungkan ke Ponsel saya menggunakan Kabel USB.

Terima Kasih 😄😘👌👍 :)

Wassalamu‘alaikum wr. wb.

Post a Comment

Previous Post Next Post