Kamis, 05 Oktober 2023

membuat aplikasi CRUD dengan SQFLite - Flutter

     Pada pembahasan kali ini, saya akan membagikan Materi sekaligus Praktikum mengenai SQFLite pada Flutter. Akan tetapi, sebelum membahas hal yang mendalam tentang SQFLite, Ada sesuatu yang harus difahami dulu, yaitu SQL. Berikut ini adalah pembahasannya.

Apa itu SQL?

    SQL Adalah sistem manajemen database relasional (RDBMS) yang dirancang untuk Aplikasi dengan arsitektur client/server atau biasa disebut sebagai bahasa yang digunakan dalam mengakses data, khususnya untuk data yang memiliki basis relasional, contohnya seperti MySQL, Postgre, SQL, Microsoft SQL Server, serta SQFLite.


Apa itu SQFLite?

    SQFLite adalah salah satu library yang mengelola sistem database lokal yang digunakan pada flutter yang menerapkan query languange (SQL). Sama seperti RDBMS lain, SQFLite juga dapat mengeksekusi perintah select, update, delete dan lain sebagainya. 


Apa saja karakteristik dari SQFLite?

    Beberapa karakteristik SQFLite yaitu sebagai berikut:

        -    Ukurannya lebih kecil dari MySQL

        -    Database tertanam langsung dalam kode program dalam bentuk file.

        -    Bertujuan untuk mengembangkan aplikasi yang bersifat stand alone  atau bisa dibilang kecil

        -    Tidak memerlukan skalabilitas yang besar

        -    Bersifat portable, tidak memerlukan server.


Apa saja tipe data yang dimiliki SQFLite?

    Tipe data pada SQFLite yaitu sebagai berikut:

    -    Integer

    -    Real (num)

    -    Text/String

    -    BLOB (Uint8list)


Adakah contoh penggunaan SQFLite untuk pembuatan aplikasi?

    Beberapa contoh penggunaan SQFLite yaitu untuk membuat aplikasi seperti:

    -    TODO List

    -    Note atau Catatan

    -    Buku Telepon

    -    Dan lain sebagainya.


Bisakah SQFLite bisa digunakan untuk semua platform?

    Platform yang sudah support dengan SQFLite yaitu sebagai berikut:

    -    Android

    -    IOS

    -    MacOS


    Jadi itulah materi mengenai SQFLite, Selanjutnya kita akan masuk pada tahap praktikum SQFLite. Untuk prosedur Praktikumnya yaitu sebagai berikut:


Praktikum Inisialisasi  SQFLite Database - Flutter

1. Siapkan packages yang akan digunakan, pada praktikum ini, akan ada dua packages yang akan            digunakan, yaitu sqflite dan path_provider. untuk link packagesnya yaitu sebagai berikut:


    -    sqflite

    -    path_provider


2. Siapkan IDE yang akan digunakan untuk praktikum, disini saya menggunakan Visual Studio Code        untuk praktikum. Langkah awal yang harus kita lakukan tentunya membuat project terlebih dahulu,        dengan cara melakukan shortcut ctrl+shift+p > Flutter:New Project > Application. Setelah itu                tentukan folder yang akan digunakan untuk menyimpan project ini.


3. Tunggu Prosesnya selesai hingga muncul tampilan seperti berikut ini:


flutter


4. Daftarkan packages yang sudah disiapkan tadi dengan cara masuk ke file pubspec.yaml, lalu di bagian dependencies daftarkan packages sqflite dan path_provider, sehingga file pubspec.yaml nya menjadi seperti berikut ini



pubspec.yaml



5. Setelah itu safe, hingga proses pub get berjalan. Jika berhasil, maka akan muncul seperti pada                gambar berikut ini:

   

flutter pub get



6. Lakukan perubahan pada file main.dart, sehingga menjadi seperti berikut ini:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      home: const MyHomePage(title: 'CRUD SQFLite'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.blue,
          title: Text(widget.title),
        ),
      );
  }
}

7. Setelah melakukan perubahan pada file main.dart, Silahkan buat file baru untuk program                        databasenya, disini saya membuatnya dengan nama "database_instance.dart".

8. Di file "database_instance.dart" import package yang akan digunakan, package yang akan digunakan     adalah seperti pada gambar berikut ini:

import 'dart:io';

import 'package:crud_sqflite/product_model.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

 9. Buat class untuk file program database, disini saya memberikan nama class "databaseInstance",             kemudian di dalam class tersebut definisikan variabel untuk nama database, versi database, nama         tabel serta variabel untuk kolom, sehingga seperti berikut ini:

class DatabaseInstance {
  final String _databaseName = 'my_database.db';
  final int _databaseVersion = 1;

  // tabel
  final String table = 'product';
  final String id = 'id';
  final String name = 'name';
  final String category = 'category';
  final String createdAt = 'created_at';
  final String updatedAt = 'updated_at';

10. Kemudian tambahkan variabel database, sehingga programnya seperti berikut ini


import 'dart:io';

import 'package:crud_sqflite/product_model.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

class DatabaseInstance {
  final String _databaseName = 'my_database.db';
  final int _databaseVersion = 1;

  // tabel
  final String table = 'product';
  final String id = 'id';
  final String name = 'name';
  final String category = 'category';
  final String createdAt = 'created_at';
  final String updatedAt = 'updated_at';

  Database? _database;
}


11. Buatlah fungsi untuk database, dimana ketika database ada, maka akan ditambilkan, sebaliknya jika       database tidak ada, maka akan terjadi proses menginisialisasi database. untuk program dari fungsi          tersebut yaitu sebagai beikut:


Future<Database> database() async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

12. untuk fungsi "_initDatabase()" yang digunakan untuk menginisialisasikan database mempunyai isi       program seperti berikut ini:

Future _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, _databaseName);
    return openDatabase(path, version: _databaseVersion, onCreate: _onCreate);
  }

13. Setelah itu, buatlah isi dari fungsi "onCreate" dengan isi seperti berikut ini:

Future _onCreate(Database db, int version) async {
    await db.execute(
        'CREATE TABLE $table ($id INTEGER PRIMARY KEY, $name TEXT NULL,
    $category TEXT NULL, $createdAt TEXT NULL, $updatedAt TEXT NULL)');
  }

    Jika semuanya sudah dibuat, maka proses inisialisasi SQFLite Database pada flutter sudah selesai, sehingga jika dilihat secara keseluruhan, maka isi dari file program database "database_instance.dart" adalah sebagai berikut ini:

import 'dart:io';

import 'package:crud_sqflite/product_model.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

class DatabaseInstance {
  final String _databaseName = 'my_database.db';
  final int _databaseVersion = 1;

  // tabel
  final String table = 'product';
  final String id = 'id';
  final String name = 'name';
  final String category = 'category';
  final String createdAt = 'created_at';
  final String updatedAt = 'updated_at';

  Database? _database;
  Future<Database> database() async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  Future _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, _databaseName);
    return openDatabase(path, version: _databaseVersion, onCreate: _onCreate);
  }

  Future _onCreate(Database db, int version) async {
    await db.execute(
        'CREATE TABLE $table ($id INTEGER PRIMARY KEY, $name TEXT NULL,
    $category TEXT NULL, $createdAt TEXT NULL, $updatedAt TEXT NULL)');
  }
}
database_instance.dart

Praktikum membuat fungsi create

    Untuk membuat fungsi create, lakukan langkah - langkah berikut ini

1.    di dalam folder lib, buat file baru dengan nama product_model.dart, kemudian untuk programnya adalah sebagai berikut:

class ProductModel {
  int? id;
  String? name, category, createdAt, updatedAt;

  ProductModel(
      {this.id, this.name, this.category, this.createdAt, this.updatedAt});

  factory ProductModel.fromJson(Map<String, dynamic> json) {
    return ProductModel(
        id: json['id'],
        name: json['name'],
        category: json['category'],
        createdAt: json['created_at'],
        updatedAt: json['updated_at']);
  }
}

product_model.dart

2.    Tambahkan fungsi untuk menampilkan database di file database_instance.dart seperti berikut ini:

Future<List<ProductModel>> all() async {
    final data = await _database!.query(table);
    List<ProductModel> result =
        data.map((e) => ProductModel.fromJson(e)).toList();
    print(result);
    return result;
  }
3.    Kemudian tambahkan lagi fungsi insert atau memasukkan database seperti berikut ini:

Future<int> insert(Map<String, dynamic> row) async {
    final query = await _database!.insert(table, row);
    return query;
  }

4.    Di file main.dart, masukkan database yang sudah diinisialisasikan sehingga menjadi seperti berikut:

class _MyHomePageState extends State<MyHomePage> {
  DatabaseInstance? databaseInstance;

  Future initDatabase() async {
    await databaseInstance!.database();
    setState(() {});
  }

  @override
  void initState() {
    databaseInstance = DatabaseInstance();
    initDatabase();
    super.initState();
  }

5.    setelah itu di bagian appbar, tambahkan icon '+ ' untuk beralih ke halaman create database, untuk menambahkan icon '+' caranya yaitu sebagai berikut:

actions: [
            IconButton(
                onPressed: () {},
                icon: Icon(Icons.add))
          ],

6.    Buatlah file baru dengan nama "create.dart" untuk halaman pembuatan data baru, isi dari file tersebut yaitu sebagai berikut:

import 'package:crud_sqflite/database_instance.dart';
import 'package:flutter/material.dart';

class CreateDb extends StatefulWidget {
  const CreateDb({super.key});

  @override
  State<CreateDb> createState() => _CreateDbState();
}

class _CreateDbState extends State<CreateDb> {
  DatabaseInstance databaseInstance = DatabaseInstance();
  TextEditingController nameController = TextEditingController();
  TextEditingController categoryController = TextEditingController();

  @override
  void initState() {
    databaseInstance.database();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue,
        title: Text('Halaman Create'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(25),
        child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          SizedBox(
            height: 20,
          ),
          Text('Nama Produk'),
          TextField(
            controller: nameController,
          ),
          SizedBox(
            height: 20,
          ),
          Text('Kategori'),
          TextField(
            controller: categoryController,
          ),
          SizedBox(
            height: 20,
          ),
          ElevatedButton(
              onPressed: () async {
                await databaseInstance.insert({
                  'name': nameController.text,
                  'category': categoryController.text,
                  'created_at': DateTime.now().toString(),
                  'updated_at': DateTime.now().toString()
                });
                Navigator.pop(context);
                setState(() {});
              },
              child: Text('SUBMIT'))
        ]),
      ),
    );
  }
}


create.dart


7. Setelah itu, kembali ke file main.dart, di bagian actions dari konfigurasi icon '+', tambahkan fungsi navigator, sehingga untuk konfigurasinya menjadi seperti berikut:

actions: [
            IconButton(
                onPressed: () {
                  Navigator.push(context, MaterialPageRoute(builder: (builder) {
                    return CreateDb();
                  }));
                },
                icon: Icon(Icons.add))
          ],

8.    Lanjut ke bagian update, buatlah file dengan nama "update.dart", kemudian isinya adalah sebagai berikut:

import 'package:crud_sqflite/database_instance.dart';
import 'package:crud_sqflite/product_model.dart';
import 'package:flutter/material.dart';

class UpdateDb extends StatefulWidget {
  final ProductModel? productModel;
  const UpdateDb({super.key, this.productModel});

  @override
  State<UpdateDb> createState() => _UpdateDbState();
}

class _UpdateDbState extends State<UpdateDb> {
  DatabaseInstance databaseInstance = DatabaseInstance();
  TextEditingController nameController = TextEditingController();
  TextEditingController categoryController = TextEditingController();

  @override
  void initState() {
    databaseInstance.database();
    nameController.text = widget.productModel!.name ?? '';
    categoryController.text = widget.productModel!.category ?? '';
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue,
        title: Text('Halaman Update'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(25),
        child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          SizedBox(
            height: 20,
          ),
          Text('Nama Produk'),
          TextField(
            controller: nameController,
          ),
          SizedBox(
            height: 20,
          ),
          Text('Kategori'),
          TextField(
            controller: categoryController,
          ),
          SizedBox(
            height: 20,
          ),
          ElevatedButton(
              onPressed: () async {
                await databaseInstance.update(widget.productModel!.id!, {
                  'name': nameController.text,
                  'category': categoryController.text,
                  'updated_at': DateTime.now().toString()
                });
                Navigator.pop(context);
                setState(() {});
              },
              child: Text('SUBMIT'))
        ]),
      ),
    );
  }
}

update.dart


9.    tambahkan lagi fungsi update pada "database_instance.dart" seperti berikut ini:

Future<int> update(int idParams, Map<String, dynamic> row) async {
    final query = await _database!
        .update(table, row, where: 'id = ?', whereArgs: [idParams]);
    return query;
  }

10.    Setelah itu, tambahkan fungsi delete lagi pada "database_instance.dart", seperti berikut ini:

Future delete(int idParams) async {
    await _database!.delete(table, where: 'id = ?', whereArgs: [idParams]);
  }

11.    Sehingga untuk keseluruhan file "database_instance.dart" menjadi:

import 'dart:io';

import 'package:crud_sqflite/product_model.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

class DatabaseInstance {
  final String _databaseName = 'my_database.db';
  final int _databaseVersion = 1;

  // tabel
  final String table = 'product';
  final String id = 'id';
  final String name = 'name';
  final String category = 'category';
  final String createdAt = 'created_at';
  final String updatedAt = 'updated_at';

  Database? _database;
  Future<Database> database() async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  Future _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, _databaseName);
    return openDatabase(path, version: _databaseVersion, onCreate: _onCreate);
  }

  Future _onCreate(Database db, int version) async {
    await db.execute(
        'CREATE TABLE $table ($id INTEGER PRIMARY KEY, $name TEXT NULL, $category TEXT NULL, $createdAt TEXT NULL, $updatedAt TEXT NULL)');
  }

  Future<List<ProductModel>> all() async {
    final data = await _database!.query(table);
    List<ProductModel> result =
        data.map((e) => ProductModel.fromJson(e)).toList();
    print(result);
    return result;
  }

  Future<int> insert(Map<String, dynamic> row) async {
    final query = await _database!.insert(table, row);
    return query;
  }

  Future<int> update(int idParams, Map<String, dynamic> row) async {
    final query = await _database!
        .update(table, row, where: 'id = ?', whereArgs: [idParams]);
    return query;
  }

  Future delete(int idParams) async {
    await _database!.delete(table, where: 'id = ?', whereArgs: [idParams]);
  }
}


12.   Di file main.dart, tambahkan program untuk menggabungkan fungsi tadi sehingga bekerja menjadi aplikasi crud, sehingga untuk file main.dart secara keseluruhan yaitu sebagai berikut:

import 'package:crud_sqflite/create.dart';
import 'package:crud_sqflite/database_instance.dart';
import 'package:crud_sqflite/product_model.dart';
import 'package:crud_sqflite/update.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      home: const MyHomePage(title: 'CRUD SQFLite'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DatabaseInstance? databaseInstance;

  Future _refresh() async {
    setState(() {});
  }

  Future initDatabase() async {
    await databaseInstance!.database();
    setState(() {});
  }

  Future delete(id) async {
    await databaseInstance!.delete(id);
    setState(() {});
  }

  @override
  void initState() {
    databaseInstance = DatabaseInstance();
    initDatabase();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.blue,
          title: Text(widget.title),
          actions: [
            IconButton(
                onPressed: () {
                  Navigator.push(context, MaterialPageRoute(builder: (builder) {
                    return CreateDb();
                  }));
                },
                icon: Icon(Icons.add))
          ],
        ),
        body: RefreshIndicator(
          onRefresh: _refresh,
          child: databaseInstance != null
              ? FutureBuilder<List<ProductModel>>(
                  future: databaseInstance!.all(),
                  builder: (context, snapshot) {
                    if (snapshot.data!.length == 0) {
                      return Center(
                        child: Text(
                          'Data Masih Kosong',
                          style: TextStyle(
                              fontWeight: FontWeight.bold, fontSize: 40),
                        ),
                      );
                    }
                    if (snapshot.hasData) {
                      return ListView.builder(
                        itemCount: snapshot.data!.length,
                        itemBuilder: (context, index) {
                          return ListTile(
                            title: Text(snapshot.data![index].name ?? ''),
                            subtitle:
                                Text(snapshot.data![index].category ?? ''),
                            leading: IconButton(
                                onPressed: () {
                                  Navigator.push(context,
                                      MaterialPageRoute(builder: (builder) {
                                    return UpdateDb(
                                        productModel: snapshot.data![index]);
                                  }));
                                },
                                icon: Icon(Icons.edit)),
                            trailing: IconButton(
                                onPressed: () =>
                                    delete(snapshot.data![index].id!),
                                icon: Icon(Icons.delete)),
                          );
                        },
                      );
                    } else {
                      return Center(
                        child: CircularProgressIndicator(color: Colors.green),
                      );
                    }
                  },
                )
              : Center(
                  child: CircularProgressIndicator(color: Colors.green),
                ),
        ));
  }
}


Untuk debugnya, saya menggunakan smartphone melalui sambungan USB. Berikut ini mookup dari aplikasi tersebut:

    Jika database masih kosong, akan muncul tampilan seperti berikut ini:

database kosong


    Kemudian untuk menambahan data baru, klik icon '+' sehingga masuk ke halaman create seperti berikut ini:

halaman create


    Disini saya akan menambahkan data baru dengan nama produk "labtop" dan kategori "informatika" pada database

tambah data

    Sehingga data muncul pada halaman utama seperti ini:

database ditambahkan

    Kemudian saya akan menambahkan data baru lagi dengan nama produk "kopi" dan kategorinya yaitu "minuman" 

tambah data 2

    Sehingga muncul pada halaman utama seperti ini:

data 2 ditambahkan

    Jika saya ingin mengedit data dari data "labtop" yang kategorinya "informatika" menjadi kategori "alat" seperti ini:

    
edit data

    Maka akan di update pada halaman utama seperti berikut ini:

data di update

    Kemudian jika saya mengklik tombol delete pada data "kopi" maka akan terhapus juga, sehingga pada halaman utama juga data kopi tidak ada, karena sudah dihapus

data dihapus





Tidak ada komentar:

Posting Komentar