Flutter Operasi CRUD tanpa Database dengan Shared Preferences

Saat kita membuat aplikasi android Ada beberapa pilihan untuk menyimpan data secara lokal di smartphone, seperti database sqlite atau Shared Preferences.

Shared Preferences adalah cara penyimpanan data pada smarthphone dengan format key value pair. Mirip dengan JSON object atau Map. Shared preferences bisa menyipan data berupa sring, integer, double atau boolean. Jika data yang diolah tidak banyak dan bukan data penting / rahasia Shared Preferences adalah pilihan yang tepat, karena proses baca dan tulisnya sangat mudah.

Pada tutorial ini saya akan membahas bagaimana membuat operasi CRUD (Create Read Update dan Delete) menggunakan Shared Preferences. Programnya sederhana saja yaitu mengumpulkan data customer berupa nama, alamat dan no telepon. Kemudian menampilkannya di List View. Serta operasi untuk edit dan delete data tersebut.

Update depedency di file pubspec.yaml

Untuk menyimpan dan membaca Shared Preferences butuh library shared_preferences. Buka file pubspec.yaml dan tambahkan kode berikut shared_preferences: dibawah blok dependencies:. Ingat di file pubspec.yaml indentasi sangat penting. Aplikasi kita bisa error jika jumlah spasi atau tab antar baris tidak sama. Kira-kira hasilnya bakal seperti ini

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  shared_preferences: # tambahkan ini

Class Helper

Untuk memudahkan proses membaca dan menulis Shared Preferences buat static class agar bisa dengan mudah dipanggil dari class lain. Pada folder lib klik kanan dan pilih New >> Dart File. Isi data.dart sebagai nama file. Masukkan kode dibawah ini.

import 'package:shared_preferences/shared_preferences.dart'; // import module untuk baca dan tulis Shared Preferences
import 'dart:convert'; // import module untuk mengubah data Shared Preferences yang berupa string menjadi list atau map dart

class Data {
    // baca data dari smartphone
    static getData() async {
        var prefs = await SharedPreferences.getInstance();

        // shared preferences menggunakan format key value pair
        // untuk membaca data kita perlu memasukkan key pada method getString
        // pastikan key adalah unik, jadi lebih baik gunakan nama domain
        var savedData = prefs.getString('ID.NGASTURI.TUTORIAL.PREF');

        // jika nilai masih null, misal saat pertama kali install
        // kita beri nilai default agar tidak error saat diconvert dengan perintah json.decode
        if(savedData == null){
            savedData = '[]';
        }
        // data yang disimpan di shared preferences sebaiknya string dengan fomat json
        // agar bisa dengan mudah diolah menjadi list atau map dart
        return json.decode(savedData);
    }

    static saveData(data) async {
        var prefs = await SharedPreferences.getInstance();

        // untuk menulis data kita memasukkkan key dan value
        // value dalam hal ini adalah variabel data yang masih dalam bentuk list atau map
        // jadi perlu diubah jadi string dengan format json
        prefs.setString('ID.NGASTURI.TUTORIAL.PREF', json.encode(data));
    }
}

Halaman Home

Di halaman Home ini kita menampilkan daftar customer dalam bentuk list. Jika list tersebut di klik akan diarahkan ke halaman Insert, sehingga user bisa edit atau hapus data tersebut. Edit file main.dart dengan kode dibawah ini.

import 'package:flutter/material.dart';
import 'insert.dart';
import 'data.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            theme: ThemeData(
                primarySwatch: Colors.blue,
            ),
            home: MyHomePage(),
        );
    }
}

class MyHomePage extends StatefulWidget {
    MyHomePage({Key key}) : super(key: key);

    @override
    _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
    // data customer yang akan ditampilkan di list view
    // beri nilai awal berupa list kosong agar tidak error
    // nantinya akan diisi data dari Shared Preferences
    var savedData = [];

    // method untuk mengambil data Shared Preferences
    getSavedData() async {
        var data = await Data.getData();
        // setelah data didapat panggil setState agar data segera dirender
        setState(() {
          savedData = data;
        });
    }

    // init state ini dipanggil pertama kali oleh flutter
    @override
    initState() {
        super.initState();
        // baca Shared Preferences
        getSavedData();
    }

    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text('Home'),
                backgroundColor: Colors.blue,
                actions: <Widget>[
                    FlatButton(
                        onPressed: (){
                            // action tombol ADD untuk proses insert
                            // nilai yang dikirim diisi null
                            // agar di halaman insert tahu jika null berarti operasi insert data
                            // jika tidak null maka update data
                            Navigator.push(
                                context,
                                MaterialPageRoute(builder: (context) => Insert(index: null, value: null))
                            ).then((value){
                                // jika halaman insert ditutup ambil kembali Shared Preferences
                                // untuk mendapatkan data terbaru dan segera ditampilkan ke user
                                // misal jika ada data customer yang ditambahkan
                                getSavedData();
                            });
                        },
                        child: Text(
                            'ADD',
                            style: TextStyle(
                                color: Colors.white
                            ),
                        ),
                    )
                ],
            ),
            body: Padding(
                padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
                child: ListView.builder(
                    itemCount: savedData.length,
                    itemBuilder: (context, index){
                        return ListTile(
                            title: Text(savedData[index]['name']),
                            subtitle: Text(savedData[index]['address'] + ' ' + savedData[index]['phone']),
                            contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 0),
                            onTap: (){
                                // aksi saat user klik pada item customer pada list view
                                // nilai diisi selain null menandakan di halaman insert operasi yang berjalan adalah update atau delete
                                Navigator.push(
                                    context,
                                    MaterialPageRoute(builder: (context) => Insert(index: index, value: savedData[index]))
                                ).then((value){
                                    // jika halaman insert ditutup ambil kembali Shared Preferences
                                    // untuk mendapatkan data terbaru dan segera ditampilkan ke user
                                    // misal jika ada data customer yang diedit atau dihapus
                                    getSavedData();
                                });
                            },
                        );
                    }
                ),
            )
        );
    }
}

Halaman Insert

Halaman ini terdapat beberapa field untuk mengisi data. Juga terdapat tombol delete. Buat file insert.dart dan tambahkan kode dibawah ini

import 'package:flutter/material.dart';
import 'data.dart';

class Insert extends StatefulWidget {
    final index;
    final value;
    Insert({Key key, @required this.index, @required this.value}) : super(key: key);



    @override
    _InsertState createState() => _InsertState(index: index, value: value);
}

class _InsertState extends State<Insert> {
    _InsertState({@required this.index, @required this.value}) : super();
    // variabel untuk menampung data yang dikirim dari halaman home
    final index;
    final value;

    // controller TextField untuk validasi
    final nameController = TextEditingController();
    final addressController = TextEditingController();
    final phoneController = TextEditingController();


    // cek semua data sudah diisi atau belum
    isDataValid() {
        if(nameController.text.isEmpty){
            return false;
        }

        if(addressController.text.isEmpty){
            return false;
        }

        if(phoneController.text.isEmpty){
            return false;
        }

        return true;
    }


    getData(){
        // jika nilai index dan value yang dikirim dari halaman home tidak null
        // artinya ini adalah operasi update
        // tampilkan data yang dikirim, sehingga user bisa edit
        if(index != null && value != null){
            setState(() {
                nameController.text = value['name'];
                addressController.text = value['address'];
                phoneController.text = value['phone'];
            });
        }
    }

    // proses menyimpan data yang diinput user ke Shared Preferences
    saveData() async {
        // cek semua data sudah diisi atau belum
        // jika belum tampilkan pesan error
        if(isDataValid()){
            // data yang akan dimasukkan atau diupdate ke Shared Preferences sesuai input user
            var customer = {
                'name': nameController.text,
                'address': addressController.text,
                'phone': phoneController.text
            };

            // ambil data Shared Preferences sebagai list
            var savedData = await Data.getData();

            if(index == null){
                // index == null artinya proses insert
                // masukkan data pada index 0 pada data Shared Preferences
                // sehingga pada halaman Home data yang baru dimasukkan
                // akan tampil paling atas
                savedData.insert(0, customer);
            }else{
                // jika index tidak null artinya proses update
                // update data Shared Preferences sesuai index-nya
                savedData[index] = customer;
            }
            // simpan data yang diinsert / diedit user ke Shared Preferences kembali
            // kemudian tutup halaman insert ini
            await Data.saveData(savedData);
            Navigator.pop(context);
        }else{
            showDialog(
                context: context,
                builder: (context){
                    return AlertDialog(
                        title: Text('Empty Field'),
                        content: Text('Please fill all field.'),
                        actions: <Widget>[
                            FlatButton(
                                onPressed: (){
                                    Navigator.pop(context);
                                },
                                child: Text('OK'),
                            )
                        ],
                    );
                }
            );
        }
    }

    deleteData() async {
        // ambil data Shared Preferences sebagai list
        // delete data pada index yang sesuai
        // kemudian simpan kembali ke Shared Preferences
        // dan kembali ke halaman Home
        var savedData = await Data.getData();
        savedData.removeAt(index);

        await Data.saveData(savedData);

        Navigator.pop(context);
    }

    getDeleteButton(){
        // jika proses update tampilkan tombol delete
        // jika insert return widget kosong
        if(index != null && value != null){
            return FlatButton(
                child: Text(
                    'DELETE',
                    style: TextStyle(
                        color: Colors.white
                    ),
                ),
                onPressed: (){
                    deleteData();
                },
            );
        }else{
            return SizedBox.shrink();
        }
    }

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

    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text('Insert'),
                backgroundColor: Colors.blue,
                actions: <Widget>[
                    getDeleteButton(),
                    FlatButton(
                        onPressed: (){
                            saveData();
                        },
                        child: Text(
                            'SAVE',
                            style: TextStyle(
                                color: Colors.white
                            ),
                        ),
                    ),
                ],
            ),
            body: Padding(
                padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                        Text('Name'),
                        TextField(
                            controller: nameController,
                        ),
                        Padding(
                            padding: EdgeInsets.only(top: 20),
                        ),
                        Text('Address'),
                        TextField(
                            controller: addressController,
                        ),
                        Padding(
                            padding: EdgeInsets.only(top: 20),
                        ),
                        Text('Phone'),
                        TextField(
                            controller: phoneController,
                        )
                    ],
                ),
            )
        );
    }

}

Berikut ini tampilan akhirnya.

Tulisan Serupa

Leave a Reply

Your email address will not be published. Required fields are marked *