0% menganggap dokumen ini bermanfaat (0 suara)
5 tayangan89 halaman

Modul Mobile3

Modul ajar Pemrograman Mobile-3 ini ditujukan untuk mahasiswa Strata-1 Program Studi Sistem Informasi Semester V, mencakup materi seperti pengantar Flutter, SQLite, dan berbagai fitur aplikasi mobile seperti login, create account, dan CRUD. Modul ini bertujuan untuk memberikan pengetahuan dan keterampilan dalam pengembangan aplikasi mobile dengan penyimpanan data lokal menggunakan SQLite. Selain itu, modul ini juga mencakup rencana pembelajaran dan sistem penilaian untuk mendukung proses belajar mengajar.
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai PDF, TXT atau baca online di Scribd
0% menganggap dokumen ini bermanfaat (0 suara)
5 tayangan89 halaman

Modul Mobile3

Modul ajar Pemrograman Mobile-3 ini ditujukan untuk mahasiswa Strata-1 Program Studi Sistem Informasi Semester V, mencakup materi seperti pengantar Flutter, SQLite, dan berbagai fitur aplikasi mobile seperti login, create account, dan CRUD. Modul ini bertujuan untuk memberikan pengetahuan dan keterampilan dalam pengembangan aplikasi mobile dengan penyimpanan data lokal menggunakan SQLite. Selain itu, modul ini juga mencakup rencana pembelajaran dan sistem penilaian untuk mendukung proses belajar mengajar.
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai PDF, TXT atau baca online di Scribd

KATA PENGANTAR

Assalamu’alaikum Warahmatullahi Wabarakatuh,


Senandung puji dan rasa syukur atas nikmat yang telah diberikan Allah SWT sehingga modul
ajar Pemrograman Mobile-3 ini dapat diselesaikan dengan baik oleh Tim Kelompok Kompetensi Dosen
STMIK Triguna Dharma.
Modul Ajar ini diperuntukkan kepada mahasiswa yang berada pada jenjang Strata-1 Program
Studi Sistem Informasi Semester V (Lima), pada modul ajar Pemrograman Mobile-3 ini akan dibahas
tentang materi pembelajaran meliputi :

1. Pengantar Flutter & SQLite


2. Model Data JSON
3. Membuat Database dan Tabel
4. UI Halaman Login
5. Proses Halaman Login
6. UI Halaman Create Account
7. Proses Halaman Create Account
8. Homepage
9. Fitur Create Data
10. Fitur Read Data
11. Fitur Update Data
12. Fitur Delete Data
13. Fitur Search Data
14. Deployment

Dengan hadirnya modul ajar ini, semoga dapat memberikan pengetahuan kepada mahasiswa
dalam mengikuti perkuliahan pada mata kuliah Pemrograman Mobile-3.
Wassalamu’alaikum Warahmatullahi Wabarakatuh

(TIM KKD MOBILE3)

i
DAFTAR ISI

KATA PENGANTAR......................................................................................................... i
DAFTAR ISI ...................................................................................................................... ii
RENCANA PEMBELAJARAN SEMESTER GENAP ................................................... iv
Pengantar Flutter & SQLite .............................................................................................. 1
1.1 Database SQLite ..................................................................................................... 1
1.2 Membuat Project Flutter ......................................................................................... 2
1.3 Menggunakan SQLite Pada Flutter ......................................................................... 3
Model Data JSON .............................................................................................................. 4
2.1 Membuat Model User ............................................................................................. 4
2.2 Membuat Model Note ............................................................................................. 7
Membuat Database dan Tabel........................................................................................... 9
3.1 Membuat Database, Tabel Users dan Tabel Notes ................................................... 9
UI Halaman Login ............................................................................................................15
4.1 Desain User Interface Halaman Login ....................................................................15
Proses Halaman Login ......................................................................................................21
5.1 Membuat TextEditingController ............................................................................21
5.2 Menampilkan dan Menyembunyikan Teks Password .............................................21
5.3 Menambahkan Validasi Form ................................................................................23
5.4 Membuat Fungsi Login ..........................................................................................25
UI Halaman Create Account ............................................................................................29
6.1 Desain User Interface Halaman Create Account .....................................................29
Proses Halaman Create Account ......................................................................................36
7.1 Membuat TextEditingController ............................................................................36
7.2 Menampilkan dan Menyembunyikan Teks Password .............................................37
7.3 Menampilkan dan Menyembunyikan Teks Confirm Password................................38
7.4 Menambahkan Validasi Form ................................................................................39
7.5 Membuat Fungsi Create Account ...........................................................................41
7.6 Membuat Navigator TextButton Login...................................................................44
Ujian Tengah Semester .....................................................................................................45
8.1 Soal UTS ...............................................................................................................45
Homepage .........................................................................................................................46
9.1 Desain User Interface Homepage ...........................................................................46
Fitur Create Data..............................................................................................................50
10.1 Desain User Interface Halaman Create Data ...........................................................50
10.2 Membuat Proses Create Data .................................................................................53

ii
Fitur Read Data ................................................................................................................59
11.1 Membuat Fungsi Menampilkan Data .....................................................................59
Fitur Update Data .............................................................................................................62
12.1 Desain User Interface Halaman Update Data ..........................................................62
12.1 Membuat Proses Update Data ................................................................................65
Fitur Delete Data ..............................................................................................................72
13.1 Desain User Interface Delete Data .........................................................................72
13.1 Membuat Proses Delete Data .................................................................................74
Fitur Search Data .............................................................................................................76
14.1 Membuat Proses Search Data .................................................................................76
Deployment .......................................................................................................................78
15.1 Deployment ...........................................................................................................78
15.1 Build APK (Android Package Kit) .........................................................................78
Ujian Akhir Semester .......................................................................................................81
16.1 Soal UAS ..............................................................................................................81

iii
RENCANA PEMBELAJARAN SEMESTER GENAP
PROGRAM STUDI : SISTEM INFORMASI
STMIK TRIGUNA DHARMA

Mata Kuliah (MOBILE3) Pemrograman Mobile-3

Mata Kuliah Prasyarat Pemrograman Mobile-2

Dosen Pengampu Faisal Taufik, [Link]., [Link].

Alokasi Waktu / Bobot SKS 16 x Pertemuan (90 Menit Tatap Muka) / 2 SKS

Mata Kuliah ini membahas tentang bagaimana cara membuat aplikasi mobile yang menggunakan media penyimpanan

Deskripsi Mata Kuliah internal sebagai media penyimpanan data menggunakan database SQLite. Materi meliputi pembuatan database, autentikasi
pengguna, menambah data baru, menampilkan data, mengubah data, menghapus data serta melakukan pencarian data.

1. Mahasiswa memiliki pengetahuan dan pemahaman tentang storage lokal (SQLite).


2. Mahasiswa memiliki kemampuan membuat database lokal menggunakan SQLite.
3. Mahasiswa memiliki kemampuan membuat aplikasi mobile dengan menggunakan database lokal sebagai media
penyimpanan data.
Capaian Pembelajaran (Kompetensi)
4. Mahasiswa memiliki kemampuan membuat aplikasi Create, Read, Update dan Delete.
5. Mahasiswa memiliki kemampuan membuat fasilitas pencarian data (search).
6. Mahasiswa memiliki kemampuan membuat aplikasi yang menerapkan sistem autentikasi (Login dan Logout).
7. Mahasiswa memiliki kemampuan melakukan build project ke APK.

iv
1. Kehadiran : 10%
2. Tugas / Evaluasi : 20%

Sistem Penilaian 3. Ujian Tengah Semester : 25%


4. Ujian Akhir Semester : 35%
5. Etika : 10%

Referensi / Sumber Pembelajaran

v
Sesi Materi Pembelajaran Sub Materi Pembelajaran Indikator Capaian Kemampuan Bentuk Pembelajaran Media Referensi

1. Database SQLite Mahasiswa memahami tentang Ruang kelas,


Pengantar Flutter &
1 2. Membuat Project Flutter penggunaan database SQLite pada Lecturing LCD, -
SQLite
3. Menggunakan SQLite Pada Flutter Flutter Whiteboard
1. Membuat Model User Ruang kelas,
Model Data JSON Mahasiswa memahami tentang
2 Lecturing and practice LCD, -
2. Membuat Model Note pembuatan model data JSON
Whiteboard
1. Membuat Database Ruang kelas,
Mahasiswa memahami dan mampu
3 Database dan Tabel Lecturing and practice LCD, -
2. Membuat Tabel membuat database dan tabel
Whiteboard
1. Desain User Interface Halaman Ruang kelas,
Mahasiswa mampu mendesain user
4 UI Halaman Login Lecturing and practice LCD, -
Login interface halaman login
Whiteboard
Ruang kelas,
Mahasiswa mampu membuat proses
5 Proses Halaman Login 1. Membuat Proses Halaman Login Lecturing and practice LCD, -
halaman login
Whiteboard
1. Desain User Interface Halaman Ruang kelas,
UI Halaman Create Mahasiswa mampu mendesain user
6 Lecturing and practice LCD, -
Account Create Account interface halaman create account
Whiteboard
Ruang kelas,
Proses Halaman Create 1. Proses Halaman Create Account Mahasiswa mampu membuat proses
7 Lecturing and practice LCD, -
Account halaman create account
Whiteboard

8 Ujian Tengah Semester


Ruang kelas,
1. Desain User Interface Homepage Mahasiswa mampu mendesain user
9 Homepage Lecturing and practice LCD, -
interface homepage
Whiteboard
1. Desain User Interface Halaman Ruang kelas,
Create Data Mahasiswa mampu membuat fitur
10 Fitur Create Data Lecturing and practice LCD, -
create data
2. Membuat Fungsi Create Data Whiteboard
1. Membuat Fungsi Menampilkan Mahasiswa mampu membuat fitur Ruang kelas,
11 Fitur Read Data Lecturing and practice -
Data read data LCD,

vi
Whiteboard
1. Desain User Interface Halaman Ruang kelas,
Mahasiswa mampu membuat fitur
12 Fitur Update Data Update Data Lecturing and practice LCD, -
update data
2. Membuat Fungsi Update Data Whiteboard
1. Desain User Interface Delete Data Ruang kelas,
Mahasiswa mampu membuat fitur
13 Fitur Delete Data Lecturing and practice LCD, -
2. Membuat Fungsi Delete Data delete data
Whiteboard
Ruang kelas,
1. Membuat Fungsi Search Data Mahasiswa mampu membuat fitur
14 Fitur Search Data Lecturing and practice LCD, -
search data
Whiteboard
1. Build APK (Android Package Mahasiswa memahami tentang Ruang kelas,
15 Deployment deployment dan melakukan build Lecturing and practice LCD, -
Kit)
APK Whiteboard
16 Ujian Akhir Semester

vii
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 1 (Satu)
Telp/Fax. 061 822 4051
[Link]

Pengantar Flutter & SQLite

1. Database SQLite
Materi Pembelajaran : 2. Membuat Project Flutter
3. Menggunakan SQLite Pada Flutter

1.1 Database SQLite

SQLite adalah sebuah mesin database relasional (RDBMS) yang ringan, cepat, dan
berbasis file. Tidak seperti sistem database besar seperti MySQL atau PostgreSQL, SQLite tidak
membutuhkan server yang berjalan secara terpisah. Ini membuatnya sangat praktis untuk
aplikasi berskala kecil hingga menengah. SQLite merupakan salah satu mesin database yang
paling banyak digunakan di seluruh dunia, dikenal karena efisiensi dan fleksibilitasnya. SQLite
tidak hanya digunakan oleh para pengembang, ia telah terintegrasi ke dalam banyak ponsel,
komputer, dan aplikasi sehari-hari yang kita gunakan, menjadikannya bagian penting dari
kehidupan digital kita.

Kapan Menggunakan SQLite?


SQLite cocok digunakan dalam situasi berikut:
 Aplikasi mobile (Android/iOS) — hampir semua aplikasi Android menggunakan
SQLite.
 Aplikasi desktop atau standalone.
 Sistem embedded (misalnya di router, kamera, IoT).
 Aplikasi web kecil atau prototipe sebelum migrasi ke sistem database yang lebih besar.
 Menyimpan data lokal untuk caching offline atau konfigurasi.

Mengapa Memilih SQLite?


 Performa: SQLite menawarkan penyimpanan data lokal dengan performa tinggi. Untuk
data lokal yang umumnya diakses oleh satu pengguna pada satu waktu, SQLite
menawarkan kinerja baca/tulis yang sangat cepat dan efisien. Ini lebih dari cukup untuk
sebagian besar kebutuhan aplikasi mobile, seperti menyimpan daftar tugas, catatan,
riwayat transaksi, pengaturan pengguna, atau data master yang statis.
 Lintas Platform: Flutter dirancang untuk pengembangan lintas platform, dan SQLite
mendukung hal ini dengan kompatibilitas untuk Android maupun iOS.
 Penyimpanan Data Offline: Ini adalah alasan paling krusial untuk aplikasi mobile.
SQLite memungkinkan aplikasi Anda menyimpan dan mengakses data secara

1
lokal di perangkat pengguna. Pengguna dapat terus menggunakan aplikasi, melihat
data, dan bahkan membuat perubahan (yang akan disinkronkan nanti) meskipun tidak
ada koneksi internet.
 Instalasi Mudah: Pengembang hanya perlu menambahkan dependensi sqflite ke
[Link], dan database siap digunakan.

Apa itu Sqflite?


Sqflite adalah paket Flutter yang menyediakan cara sederhana dan efisien untuk bekerja
dengan database SQLite dalam aplikasi Flutter Anda. Paket ini ringan, mudah digunakan, dan
sangat cocok untuk mengelola data lokal. Semua operasi dalam paket ini bersifat asinkron, yang
berarti berjalan di latar belakang tanpa mengganggu antarmuka pengguna, sehingga menjaga
performa aplikasi tetap lancar.

1.2 Membuat Project Flutter

1. Buat project baru dengan nama notes_app.


2. Tambahkan beberapa baris kode pada file [Link] seperti berikut.

[Link]
import 'package:flutter/[Link]';

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

class MainApp extends StatelessWidget {


const MainApp({[Link]});

@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Notes App',
theme: ThemeData(
colorScheme: [Link](
seedColor: [Link],
),
),
home: const Scaffold(
body: Center(
child: Text('Notes App'),
),

2
),
);
}
}

1.3 Menggunakan SQLite Pada Flutter

1. Tambahkan package sqflite dan beberapa package lainnya yang dibutuhkan dalam
pengembangan aplikasi.
a. Buka jendela Terminal dan Jalankan command berikut :
flutter pub add sqflite
flutter pub add path
flutter pub add intl
flutter pub add path_provider

Package Keterangan
SQLite plugin untuk Flutter, digunakan untuk menyimpan data lokal
sqflite
di database SQLite.
Manipulasi path file sistem, kegunaan untuk menggabungkan dan
path
memanipulasi path file atau direktori secara cross-platform.
Formatting data internasional, untuk format tanggal, waktu, angka,
intl
dan localization.
Akses direktori khusus perangkat, untuk mendapatkan path direktori
path_provider
seperti dokumen, temporary, atau aplikasi

b. Buka file [Link]. Setelah menjalankan beberapa command sebelumnya maka


pada file [Link] akan ditambahkan beberapa baris kode berikut :

[Link]
dependencies:
flutter:
sdk: flutter
intl: ^0.19.0
path: ^1.8.3
path_provider: ^2.1.3
sqflite: ^2.3.2

c. Selain menambahkan melalui command pada jendela terminal, bisa juga dengan cara
menambahkan langsung package tersebut pada file [Link] lalu simpan (ctrl + s).

3
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 2 (Dua)
Telp/Fax. 061 822 4051
[Link]

Model Data JSON

1. Membuat Model User


Materi Pembelajaran :
2. Membuat Model Note

Dalam pengembangan aplikasi Flutter, model data JSON adalah representasi terstruktur
dari data yang diterima atau dikirim ke API, database, atau penyimpanan lokal. JSON
(JavaScript Object Notation) adalah format pertukaran data yang ringan dan mudah dibaca,
sementara model data di Dart/Flutter membantu mengkonversi JSON menjadi objek yang lebih
mudah dikelola, dan bisa dikatakan bahwa model data adalah cara terstruktur untuk mengelola
data di Flutter.

Mengapa Membuat Model Data JSON?


Manfaat Penjelasan
Struktur Data Model memastikan setiap data memiliki struktur dan tipe yang jelas
yang Konsisten (misalnya: id:int, judul:String, dll).
Dart akan memberi peringatan jika tipe tidak cocok (misalnya String vs
Type safety
int)
Kemudahan
Mudah konversi dari/ke database (toMap() dan fromMap())
parsing
Konsistensi Tidak perlu ketik "judul", "isi" berulang-ulang
Reusabilitas Bisa digunakan untuk API, SQLite, form input, dll.
Mudah Dirawat & Jika struktur data berubah (misal menambah kolom), cukup ubah
Dikembangkan model — tidak perlu ubah semua kode SQL/Map manual.

2.1 Membuat Model User

1. Tambahkan 1 buah folder di dalam folder lib dengan nama models.


2. Tambahkan 1 buah file di dalam folder models dengan nama user_model.dart.

4
3. Buat model user yang merepresentasikan entitas "pengguna" (User), dengan membuat kode
seperti berikut pada file user_model.dart:

user_model.dart
class UserModel {
final int? userId;
final String userName;
final String userPassword;

UserModel({
[Link],
required [Link],
required [Link],
});

factory [Link](Map<String, dynamic> json) => UserModel(


userId: json["userId"],
userName: json["userName"],
userPassword: json["userPassword"],
);

Map<String, dynamic> toMap() => {


"userId": userId,
"userName": userName,
"userPassword": userPassword,
};
}

class UserModel {...}

Ini adalah deklarasi sebuah kelas bernama UserModel. Dalam pemrograman berorientasi
objek, kelas adalah blueprint atau cetakan untuk membuat objek.

final int? userId;


final String userName;
final String userPassword;

Bagian ini merupakan Properti (Attributes) dari UserModel. Penggunaan kata kunci final
berarti bahwa nilai userId, userName, userPassword hanya dapat ditetapkan sekali saat
objek UserModel dibuat (melalui konstruktor) dan tidak dapat diubah setelahnya. Dan
Tanda ? menunjukkan bahwa userId bisa bernilai null. Ini berguna ketika membuat objek

5
UserModel baru sebelum disisipkan ke database, di mana userId mungkin belum
ditetapkan (karena biasanya dihasilkan oleh database).

UserModel({
[Link],
required [Link],
required [Link],
});

Ini adalah konstruktor untuk kelas UserModel. Konstruktor adalah metode khusus yang
dipanggil saat membuat instance (objek) baru dari kelas ini. Kata kunci required berarti
kita harus menyediakan nilai untuk userName, userPassword saat membuat objek
UserModel. Tanpa nilai ini, kode akan menghasilkan error saat kompilasi.

factory [Link](Map<String, dynamic> json) => UserModel(


userId: json["userId"],
userName: json["userName"],
userPassword: json["userPassword"],
);

Ini adalah factory constructor bernama fromMap. Factory constructor digunakan ketika kita
ingin memiliki lebih banyak kontrol atas bagaimana objek dibuat. Dalam kasus ini, fromMap
digunakan untuk membuat objek UserModel dari sebuah Map<String, dynamic>.
 Kata kunci factory menunjukkan bahwa ini adalah factory constructor. Berbeda dengan
konstruktor reguler, factory constructor tidak selalu membuat instance baru dari kelas; ia
bisa mengembalikan instance yang sudah ada atau melakukan logika lain sebelum
membuat instance baru.
 Map<String, dynamic> json: Parameter ini adalah sebuah Map yang diasumsikan berisi
data pengguna, biasanya dalam format JSON yang telah didekodekan. Kunci dari Map
adalah String (misalnya, "userId", "userName") dan nilainya bisa berupa tipe data apa
pun (dynamic).
 =>: Ini adalah sintaks arrow function atau fat arrow di Dart, yang merupakan singkatan
untuk fungsi yang hanya memiliki satu ekspresi pengembalian.
 UserModel(...): Di sini, data dari json (Map) diekstrak dan digunakan untuk memanggil
konstruktor utama UserModel untuk membuat objek baru. Misalnya, json["userId"]
akan mengambil nilai yang terkait dengan kunci "userId " dari map.
Fungsi utama fromMap: Konversi data dari format Map (seringkali dari JSON yang diterima
dari API atau database) menjadi objek UserModel yang terstruktur.

6
Map<String, dynamic> toMap() => {
"userId": userId,
"userName": userName,
"userPassword": userPassword,
};

Ini adalah sebuah metode instance bernama toMap. Metode ini berfungsi kebalikan dari
fromMap. userId, userName, userPassword: Nilai-nilai dari properti objek UserModel saat
ini diambil dan dijadikan nilai dalam Map.
Fungsi utama toMap: Konversi objek UserModel menjadi format Map. Ini sangat umum
untuk serialisasi data, yaitu mempersiapkan data untuk dikirim ke API, disimpan ke
database atau disimpan ke local storage.

2.2 Membuat Model Note

1. Tambahkan 1 buah file di dalam folder models dengan nama note_model.dart.

4. Buat model note dengan menambahkan baris kode berikut pada file note_model.dart:

note_model.dart
class NoteModel {
final int? noteId;
final String noteTitle;
final String noteContent;
final String createdAt;

NoteModel({
[Link],
required [Link],
required [Link],
required [Link],
});

factory [Link](Map<String, dynamic> json) => NoteModel(


noteId: json["noteId"],
noteTitle: json["noteTitle"],
noteContent: json["noteContent"],

7
createdAt: json["createdAt"],
);

Map<String, dynamic> toMap() => {


"noteId": noteId,
"noteTitle": noteTitle,
"noteContent": noteContent,
"createdAt": createdAt,
};
}

Penjelasan kode sama seperti class UserModel.

8
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 3 (Tiga)
Telp/Fax. 061 822 4051
[Link]

Database dan Tabel

1. Membuat Database
Materi Pembelajaran :
2. Membuat Tabel

3.1 Membuat Database, Tabel Users dan Tabel Notes

1. Tambahkan 1 buah folder di dalam folder lib dengan nama database.


2. Tambahkan 1 buah file di dalam folder database dengan nama database_helper.dart.

3. Buat database, tabel users dan tabel notes dengan menambahkan baris kode berikut pada file
database_helper.dart :

database_helper.dart
import 'package:path/[Link]';
import 'package:sqflite/[Link]';

class DatabaseHelper {
// Singleton instance
static final DatabaseHelper _instance = DatabaseHelper._internal();
factory DatabaseHelper() => _instance;
DatabaseHelper._internal();

// Configuration variables
static Database? _database;
final String databaseName = "[Link]";
final int databaseVersion = 1;

// Create user table


final String createUserTable = '''
CREATE TABLE users (
userId INTEGER PRIMARY KEY AUTOINCREMENT,
userName TEXT UNIQUE NOT NULL,
userPassword TEXT NOT NULL
)
''';

9
// create note table
final String createNoteTable = '''
CREATE TABLE notes (
noteId INTEGER PRIMARY KEY AUTOINCREMENT,
noteTitle TEXT NOT NULL,
noteContent TEXT NOT NULL,
createdAt TEXT DEFAULT CURRENT_TIMESTAMP
)
''';

// Initialize the database


Future<Database> initDB() async {
final databasePath = await getDatabasesPath();
final path = join(databasePath, databaseName);

return openDatabase(
path,
version: databaseVersion,
onCreate: (db, version) async {
await [Link](createUserTable);
await [Link](createNoteTable);
},
);
}

// Getter database instance


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

1. // Singleton instance
Bagian ini merupakan implementasi dari pola desain Singleton dalam Dart/Flutter. Pola
ini memastikan bahwa kelas DatabaseHelper hanya memiliki satu instance tunggal yang
bisa dibuat dan diakses sepanjang siklus hidup aplikasi. Secara sederhana, ini berarti
hanya ada satu "pengurus database" yang aktif. Setiap kali "pengurus database" itu
diminta, akan selalu didapatkan instance yang sama, bukan yang baru.

10
Keuntungan Utama Penggunaan Singleton pada DatabaseHelper:
1) Efisiensi dan Penghematan Sumber Daya: Mencegah pembuatan koneksi database
ganda, tidak perlu membuka dan menutup koneksi database berkali-kali, yang bisa
memakan sumber daya. Satu koneksi, digunakan bersama.
2) Konsistensi Data: Menjamin semua bagian aplikasi berinteraksi dengan instance
database yang sama. Hal ini menjaga konsistensi data dan menghindari potensi error
atau konflik yang bisa timbul jika ada banyak koneksi database yang berbeda.
3) Manajemen Terpusat: Menyediakan satu titik kontrol untuk semua operasi database,
membuat pengelolaan dan pemeliharaan kode lebih mudah.

static final DatabaseHelper _instance = DatabaseHelper._internal();

Bagian ini mendeklarasikan sebuah variabel bernama _instance dengan tipe


DatabaseHelper. Variabel ini akan menyimpan satu-satunya objek DatabaseHelper
yang ada. Kata kunci static, berarti _instance adalah properti milik kelas
DatabaseHelper itu sendiri, bukan milik objek individual dari DatabaseHelper.
Sedangkan DatabaseHelper._internal() merupakan bagian yang saat aplikasi
dimulai, atau saat pertama kali DatabaseHelper dibutuhkan, ia akan secara otomatis
memanggil konstruktor pribadi (private constructor) _internal() untuk membuat satu-
satunya instance dari DatabaseHelper.

factory DatabaseHelper() => _instance;

Bagian ini membuat sebuah konstruktor publik yang akan dipanggil di bagian lain kode
kita nanti dengan nama DatabaseHelper(). Setiap kali kita memanggil
DatabaseHelper() maka konstruktor factory ini akan selalu mengembalikan satu-
satunya objek _instance yang sudah ada.

DatabaseHelper._internal();

Konstruktor ini hanya dipanggil satu kali oleh baris pertama (static final...) untuk
membuat instance awal _instance. Karena ini pribadi, tidak ada bagian lain dari kode
kita yang bisa membuat DatabaseHelper baru.

2. // Configuration variables
Mendeklarasikan beberapa variabel yang akan digunakan untuk mengatur dan mengakses
database SQLite yang akan dibuat.

static Database? _database;

11
Variabel _database akan menjadi objek koneksi ke database yang sebenarnya.

final String databaseName = "[Link]";

Variabel databaseName merupakan nama file database yang akan dibuat di perangkat.

final int databaseVersion = 1;

Variabel databaseVersion merupakan nomor versi database, penting untuk


migrasi (perubahan struktur) database di masa mendatang.

3. // Create user table


Merupakan bagian dari definisi skema database kita. Berisi perintah SQL (Structured
Query Language) yang digunakan untuk membuat sebuah tabel baru di database SQLite
yang akan dibuat dengan nama tabel users yang digunakan untuk menympan data
pengguna aplikasi (users).

4. // Create note table


Merupakan bagian dari definisi skema database kita. Berisi perintah SQL (Structured
Query Language) yang digunakan untuk membuat sebuah tabel baru di database SQLite
yang akan dibuat dengan nama tabel notes yang digunakan untuk menyimpan data
catatan (notes).

5. // Initialize the database


berfungsi untuk menginisialisasi dan membuka database SQLite di aplikasi Flutter. Ini
adalah langkah krusial sebelum aplikasi bisa menyimpan atau mengambil data.

async, await, future


Dalam pemrograman Dart, async adalah kata kunci yang digunakan untuk menandai
suatu fungsi sebagai asynchronous (tidak berjalan secara sekuensial/berurutan). Fungsi
yang dideklarasikan dengan async akan mengembalikan sebuah Future, yang merupakan
representasi dari nilai yang mungkin belum tersedia sekarang tetapi akan tersedia di masa
depan (setelah operasi selesai).

Fungsi Utama async:


1) Menjalankan operasi yang membutuhkan waktu tanpa memblokir eksekusi
program (misalnya: mengambil data dari API, database, membaca file, atau operasi
I/O lainnya).
2) Memungkinkan penggunaan await di dalam fungsi tersebut untuk menunggu hasil
dari Future tanpa menghentikan eksekusi kode lainnya.

12
Future<Database> initDB() async {...}

Ini adalah sebuah fungsi asinkron (async) bernama initDB. Fungsi ini akan
mengembalikan sebuah Future<Database>, yang berarti ia akan menghasilkan objek
Database di masa depan (setelah proses inisialisasi selesai). Menggunakan Future dan
async/await sangat penting karena operasi database (seperti membuka file) bisa
memakan waktu dan kita tidak ingin aplikasi macet saat menunggu.

final databasePath = await getDatabasesPath();

getDatabasesPath() adalah fungsi dari paket sqflite yang digunakan untuk


mendapatkan lokasi standar di perangkat tempat database disimpan. Dan kata kunci
await digunakan karena getDatabasesPath() juga merupakan operasi asinkron.

final path = join(databasePath, databaseName);

join() adalah fungsi dari paket path (biasanya package:path/[Link]) yang


digunakan untuk menggabungkan bagian-bagian path menjadi satu path lengkap yang
benar. Di sini, databasePath (lokasi folder) digabungkan dengan databaseName (nama
file database, yaitu [Link]) untuk mendapatkan path lengkap ke file database.

return openDatabase()

openDatabase() adalah fungsi dari sqflite yang bertanggung jawab untuk membuka
koneksi ke database. Jika database belum ada, openDatabase() akan secara otomatis
membuatnya di lokasi yang ditentukan dan jika database sudah ada, ia hanya akan
membuka koneksi ke database tersebut.

path

path lengkap ke file database yang akan dibuka atau dibuat.

version: databaseVersion

version adalah nomor versi database. Ini sangat penting untuk migrasi database.

onCreate: (db, version) async {...}

onCreate adalah sebuah callback (fungsi yang dipanggil kembali) yang akan dieksekusi
hanya sekali, yaitu saat database pertama kali dibuat di perangkat pengguna. Di dalam
onCreate, kita menerima objek db (yang merupakan instance dari Database) dan version.

13
await [Link](createUserTable)
await [Link](createNoteTable);

Bagian ini menjalankan perintah SQL yang ada pada variabel createUserTable dan
createNoteTable untuk membuat tabel users dan tabel notes di database.

6. // Getter database instance


Fungsi dari bagian ini untuk mendapatkan instance (objek) database kita. Ini adalah inti
dari cara kita berinteraksi dengan database setelah kita mendefinisikan strukturnya.

Future<Database> get database async {...}

get database Ini adalah sintaks untuk getter. Artinya, kita bisa mengaksesnya seperti
sebuah properti (misalnya, await DatabaseHelper().database;).

if (_database != null) return _database!;

if (_database != null): Ini adalah pemeriksaan awal yang sangat penting. Baris ini
memeriksa apakah objek _database sudah ada dan tidak null (yaitu, database sudah
dibuka dan siap digunakan). Jika _database sudah ada, maka fungsi ini akan langsung
mengembalikan objek database yang sudah ada tersebut. Tanda seru (!) setelah
_database adalah operator "null assertion". Ini memberi tahu Dart bahwa "Saya yakin
_database tidak null di sini, jadi silakan perlakukan sebagai Database non-null." kita
bisa yakin karena kita baru saja memeriksa bahwa itu != null.

_database = await initDB();

Baris ini hanya akan dieksekusi jika _database masih null. Dan await initDB()
adalah bagian yang akan menginisialisasi (membuka atau membuat) database dan
menjalankan perintah laiinya yang ada pada fungsi initDB().

return _database!;

Setelah _database berhasil diinisialisasi (atau jika sudah ada dari awal), baris ini akan
mengembalikan objek _database yang sekarang berisi koneksi database yang aktif.

14
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 4 (Empat)
Telp/Fax. 061 822 4051
[Link]

UI Halaman Login

Materi Pembelajaran : 1. Desain User Interface Halaman Login

4.1 Desain User Interface Halaman Login

1. Tambahkan 1 buah folder di dalam folder lib dengan nama auth.


2. Tambahkan 1 buah file di dalam folder auth dengan nama login_screen.dart.

3. Buat 1 buah class pada file login_screen.dart dengan nama LoginScreen menggunakan
StatefulWidget, lalu tambahkan widget Scaffold sebagai struktur dasar halaman.
Tambahkan juga sebuah properti body pada widget Scaffold untuk menentukan konten
yang akan ditampilkan pada halaman login.

login_screen.dart
import 'package:flutter/[Link]';

class LoginScreen extends StatefulWidget {


const LoginScreen({[Link]});

@override
State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {


@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text("Halaman Login"),
),
);
}
}

15
4. Modifikasi file [Link]. Ubah properti home pada MaterialApp sehingga halaman
pertama yang akan ditampilkan pada saat aplikasi dijalankan adalah LoginScreen.

[Link]
...
home: const LoginScreen(),
...

5. Hasil dari perubahan kode yang telah dilakukan ketika aplikasi dijalankan :

6. Menambahkan sebuah gambar yang akan digunakan pada halamann login. Tambahkan 1
buah folder di dalam folder lib dengan nama images lalu copy sebuah gambar didalamnya.
Contoh sebuah gambar yang akan digunakan dengan nama [Link].

[Link]

7. Modifikasi file [Link]. Tambahkan perintah untuk mendaftarkan file aset (gambar)
yang akan digunakan pada aplikasi seperti berikut.

[Link]
flutter:
uses-material-design: true
assets:

16
- lib/images/

8. Modifikasi file login_screen.dart. Ubah bagian properti body menjadi seperti berikut
untuk membuat sebuah form dan menampilkan gambar yang digunakan.

login_screen.dart
...
body: Center(
child: SingleChildScrollView(
child: Padding(
padding: const [Link](10.0),
child: Form(
child: Column(
children: [
[Link](
'lib/images/[Link]',
width: 300,
),
],
),
),
),
),
),
...

9. Menambahkan text brand aplikasi dibawah gambar. Tambahkan beberapa baris kode seperti
berikut dibawah widget Image.

login_screen.dart
...
const SizedBox(height: 15),
const Text(
"Notes App",
style: TextStyle(
fontSize: 22,
color: [Link],
fontWeight: [Link],
),
),
...

17
10. Membuat textfield untuk inputan username. Tambahkan beberapa baris kode berikut
dibawah widget Text "Notes App".

login_screen.dart
...
const SizedBox(height: 8),
Container(
margin: const [Link](8),
padding: const [Link](
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
borderRadius: [Link](6),
color: [Link](.1),
),
child: TextFormField(
textAlignVertical: [Link],
decoration: const InputDecoration(
icon: Icon([Link]),
border: [Link],
hintText: "Username",
),
),
),
...

11. Membuat textfield untuk inputan password. Tambahkan beberapa baris kode berikut
dibawah TextFormField "Username".

login_screen.dart
...
Container(
margin: const [Link](8),
padding: const [Link](
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
borderRadius: [Link](6),
color: [Link](.1),
),
child: TextFormField(

18
textAlignVertical: [Link],
decoration: InputDecoration(
icon: const Icon([Link]),
border: [Link],
hintText: "Password",
suffixIcon: IconButton(
onPressed: () {
setState(() {});
},
icon: const Icon([Link]),
),
),
),
),
...

12. Membuat button login. Tambahkan beberapa baris kode berikut dibawah TextFormField
"Password".

login_screen.dart
...
Container(
margin: const [Link](left: 8, top: 8, right: 8),
height: 55,
width: [Link],
child: ElevatedButton(
onPressed: () {},
style: [Link](
shape: RoundedRectangleBorder(
borderRadius: [Link](6),
)),
child: const Row(
mainAxisSize: [Link],
children: [
Icon([Link]),
SizedBox(width: 8),
Text(
"Login",
style: TextStyle(
color: [Link],
fontSize: 18,
fontWeight: [Link],

19
),
),
],
),
),
),
...

13. Membuat button Create account yang berfungsi untuk membuka halaman buat akun
pengguna. Tambahkan beberapa baris kode berikut dibawah button login.

login_screen.dart
...
Row(
mainAxisAlignment: [Link],
children: [
const Text("Don't have an account?"),
TextButton(
onPressed: () {},
child: const Text("Create account"),
),
],
),
...

14. Hasil dari desain user interface halaman login.

20
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 5 (Lima)
Telp/Fax. 061 822 4051
[Link]

Proses Halaman Login

Materi Pembelajaran : 1. Proses Halaman Login

5.1 Membuat TextEditingController

1. Tambahkan 2 buah TextEditingController di dalam class _LoginScreenState untuk


mengontrol atau memantau teks yang diketik pada TextFormField username dan
TextFormField password.

login_screen.dart
...
class _LoginScreenState extends State<LoginScreen> {
final usernameController = TextEditingController();
final passwordController = TextEditingController();
...

2. Tambahkan properti controller pada TextFormField username untuk menghubungkan


TextFormField ke TextEditingController username.

login_screen.dart
...
child: TextFormField(
controller: usernameController,
...

3. Tambahkan properti controller pada TextFormField password untuk menghubungkan


TextFormField ke TextEditingController password.

login_screen.dart
...
child: TextFormField(
controller: passwordController,
...

5.2 Menampilkan dan Menyembunyikan Teks Password

1. Tambahkan 1 buah variabel isVisible dengan tipe data boolean. Nilai variabel secara
default bernilai false yang berarti teks pada password akan disembunyikan.

21
login_screen.dart
...
final passwordController = TextEditingController();

bool isVisible = false;


...

2. Tambahkan properti obscureText pada TextFormField password yang berfungsi untuk


menampilkan atau menyembunyikan teks password.

login_screen.dart
...
child: TextFormField(
controller: passwordController,
obscureText: !isVisible,
...

3. Tambahkan perintah untuk menampilkan dan menyembunyikan teks password pada


IconButton visibility yang terdapat pada TextFormField password.

login_screen.dart
...
hintText: "Password",
suffixIcon: IconButton(
onPressed: () {
setState(() {
isVisible = !isVisible;
});
},
icon: Icon(isVisible
? [Link]
: Icons.visibility_off),
),
...

4. Hasil untuk menampilkan dan menyembunyikan teks password.

22
5.3 Menambahkan Validasi Form

1. Tambahkan 1 buah variabel GlobalKey<FormState> untuk mengecek apakah semua input


pada form valid.

login_screen.dart
...
bool isVisible = false;

final formKey = GlobalKey<FormState>();


...

2. Tambahkan properti key pada widget Form.

login_screen.dart
...
child: Form(
key: formKey,
...

3. Tambahkan properti validator pada TextFormField username.

login_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "username is required";
}
return null;

23
},
...

4. Tambahkan properti validator pada TextFormField password.

login_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "password is required";
}
return null;
},
...

5. Setelah properti validator ditambahkan pada masing-masing TextFormField, selanjutnya


adalah melakukan pengecekan validasi pada button login. tambahkan kode berikut pada
properti onPressed button login.

login_screen.dart
...
onPressed: () {
if ([Link]!.validate()) {}
},
...

6. Hasil yang ditampilkan setelah validasi dibuat. Ketika button login di tap sedangkan
username dan password tidak diisi maka akan muncul pesan validasi seperti gambar berikut.

24
5.4 Membuat Fungsi Login

1. Buat fungsi login di dalam file database_helper.dart. Jika pada tabel users ditemukan
baris (pengguna) yang memiliki userName dan userPassword yang sama dengan yang
dimasukkan oleh pengguna (artinya result tidak kosong), berarti login berhasil, dan fungsi
akan mengembalikan true. Jika tidak ditemukan (artinya result kosong), berarti login
gagal, dan fungsi mengembalikan false.

database_helper.dart
import '../models/user_model.dart';
...
...

// Login method
Future<bool> login(UserModel user) async {
final db = await database;

final result = await [Link](


'users',
where: 'userName = ? AND userPassword = ?',
whereArgs: [[Link], [Link]],
);

return [Link];
}
...

2. Buat proses login (sementara) pada file login_screen.dart. Tambahkan beberapa baris
kode berikut di dalam class _LoginScreenState, pastikan lakukan import file
database_helper.dart dan user_model.dart. Proses yang dibuat adalah; mengambil
inputan userName dan userPassword dari pengguna, lalu dikirimkan ke database untuk
diverifikasi, menuggu hasil (response) berhasil atau tidak, jika berhasil akan ditampilkan
snackbar dengan pesan 'Login success', dan jika tidak berhasil akan ditampilkan pesan
'Login failed! Please try again.'.

login_screen.dart
import '../database/database_helper.dart';
import '../models/user_model.dart';
...

...
final formKey = GlobalKey<FormState>();

25
final db = DatabaseHelper();

// Fungsi Login
Future<void> login() async {
try {
var response = await [Link](
UserModel(
userName: [Link],
userPassword: [Link],
),
);

if (!mounted) return;

if (response == true) {
[Link](context).showSnackBar(
SnackBar(
content: const Text('Login success'),
backgroundColor: [Link][400],
behavior: [Link],
),
);

// Navigasi ke halaman Notes jika login berhasil


// akan dibuat nanti setelah halaman Notes dibuat

} else {
[Link](context).showSnackBar(
const SnackBar(
content: Text('Login failed! Please try again.'),
backgroundColor: [Link],
behavior: [Link],
),
);
}
} catch (e) {
if (!mounted) return;

[Link](context).showSnackBar(
SnackBar(
content: Text(' Login failed! Please try again.'),

26
backgroundColor: [Link],
behavior: [Link],
),
);
}
}
...

if (!mounted) return;

 mounted: Adalah properti yang bernilai true jika widget Anda masih "terpasang" di
pohon widget (masih terlihat di layar).
 if (!mounted) return: Melakukan pengecekan keamanan yang penting di Flutter,
terutama dalam widget StatefulWidget yang asinkron. "Jika widget ini sudah tidak ada di
layar (misalnya, pengguna sudah pindah halaman), maka berhenti jalankan kode ini." Ini
mencegah kesalahan (error) jika aplikasi mencoba memperbarui UI pada widget yang
sudah tidak ada.

3. Panggil fungsi login() pada button login.

login_screen.dart
...
onPressed: () {
if ([Link]!.validate()) {
login();
}
},
...

4. Hasil login sementara. Jika login gagal, misal user tidak ditemukan atau password salah,
maka akan muncul sebuah SnackBar dengan pesan “Login failed!. Please try
again”.

27
Nb :
1. Untuk menguji login jika berhasil belum bisa dikarenakan belum ada akun yang
terdaftar di dalam tabel users.
2. Proses login jika berhasil belum selesai, akan dilakukan modifikasi kode pada bab
berikutnya karena belum ada class yang dibuat untuk menampilkan halaman notes
ketika login berhasil.

28
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 6 (Enam)
Telp/Fax. 061 822 4051
[Link]

UI Halaman Create Account

Materi Pembelajaran : 1. Desain User Interface Halaman Create Account

6.1 Desain User Interface Halaman Create Account

1. Tambahkan 1 buah file di dalam folder auth dengan nama create_account_screen.dart.

2. Buat 1 buah class pada file create_account_screen.dart dengan nama CreateAccount


menggunakan StatefulWidget, lalu tambahkan widget Scaffold sebagai struktur dasar
halaman. Tambahkan juga sebuah properti body pada widget Scaffold untuk menentukan
konten yang akan ditampilkan pada halaman create account.

create_account_screen.dart
import 'package:flutter/[Link]';

class CreateAccount extends StatefulWidget {


const CreateAccount({[Link]});

@override
State<CreateAccount> createState() => _CreateAccountState();
}

class _CreateAccountState extends State<CreateAccount> {


@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text("Halaman Create Account"),
),
);
}
}

29
3. Modifikasi kode button Create account pada file login_screen.dart. tambahkan perintah
untuk membuka halaman Create Account ketika TextButton di tap.

login_screen.dart
...
import 'create_account_screen.dart';

...
onPressed: () {
[Link](
context,
MaterialPageRoute(
builder: (context) => const CreateAccount(),
),
);
},
child: const Text("Create account"),
...

4. Hasil yang ditampilkan ketika button Create account di tap akan membuka halaman Create
Account seperti yang terlihat pada gambar berikut.

5. Modifikasi file create_account_screen.dart. Ubah konten halaman Create Account.

create_account_screen.dart
...
return Scaffold(
body: Center(

30
child: SingleChildScrollView(
child: Form(
child: Padding(
padding: const [Link](8.0),
child: Column(
mainAxisAlignment: [Link],
children: [
const ListTile(
title: Center(
child: Text(
"Create a New Account",
style: TextStyle(
fontSize: 22,
fontWeight: [Link],
color: [Link],
),
),
),
),
],
),
),
),
),
),
);
...

6. Membuat TextFormField untuk inputan username. Tambahkan beberapa baris kode berikut
dibawah widget ListTile.

create_account_screen.dart
...
// TextFormField Username
Container(
margin: const [Link](8),
padding: const [Link](
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
borderRadius: [Link](6),

31
color: [Link](.1),
),
child: TextFormField(
textAlignVertical: [Link],
decoration: const InputDecoration(
icon: Icon([Link]),
border: [Link],
hintText: "Username",
),
),
),
...

7. Membuat TextFormField untuk inputan password. Tambahkan beberapa baris kode berikut
dibawah TextFormField Username.

create_account_screen.dart
...
// TextFormField Password
Container(
margin: const [Link](8),
padding: const [Link](
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
borderRadius: [Link](6),
color: [Link](.1),
),
child: TextFormField(
textAlignVertical: [Link],
decoration: InputDecoration(
icon: const Icon([Link]),
border: [Link],
hintText: "Password",
suffixIcon: IconButton(
onPressed: () {},
icon: const Icon([Link]),
),
),
),
),

32
...

8. Membuat TextFormField untuk inputan confirm password. Tambahkan beberapa baris kode
berikut dibawah TextFormField Password.

create_account_screen.dart
...
// TextFormField Confirm Password
Container(
margin: const [Link](8),
padding: const [Link](
horizontal: 10,
vertical: 4,
),
decoration: BoxDecoration(
borderRadius: [Link](6),
color: [Link](.1),
),
child: TextFormField(
textAlignVertical: [Link],
decoration: InputDecoration(
icon: const Icon([Link]),
border: [Link],
hintText: "Confirm Password",
suffixIcon: IconButton(
onPressed: () {},
icon: const Icon([Link]),
),
),
),
),
...

9. Membuat button create account. Tambahkan beberapa baris kode berikut dibawah
TextFormField Confirm Password.

create_account_screen.dart
...
// Button Create Account
Container(
margin: const [Link](left: 8, top: 8, right: 8),
height: 55,
width: [Link],

33
child: ElevatedButton(
onPressed: () {},
style: [Link](
shape: RoundedRectangleBorder(
borderRadius: [Link](6),
)),
child: const Row(
mainAxisSize: [Link],
children: [
Icon(Icons.person_add_alt_1),
SizedBox(width: 8),
Text(
"Create Account",
style: TextStyle(
color: [Link],
fontSize: 18,
fontWeight: [Link],
),
),
],
),
),
),
...

10. Membuat TextButton login untuk membuka halaman login. Tambahkan beberapa baris
kode berikut dibawah Button Create Account.

create_account_screen.dart
...
// TextButton Login
Row(
mainAxisAlignment: [Link],
children: [
const Text("Already have an account?"),
TextButton(
onPressed: () {},
child: const Text("Login"),
),
],
),
...

34
15. Hasil dari desain user interface halaman create account dapat dilihat pada gambar berikut.

35
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 7 (Tujuh)
Telp/Fax. 061 822 4051
[Link]

Proses Halaman Create Account

Materi Pembelajaran : 1. Proses Halaman Create Account

7.1 Membuat TextEditingController

1. Tambahkan 3 buah TextEditingController di dalam class _CreateAccountState untuk


mengontrol atau memantau teks yang diketik pada TextFormField username,
TextFormField password, dan TextFormField confirm password.

create_account_screen.dart
...
class _CreateAccountState extends State<CreateAccount> {
final usernameController = TextEditingController();
final passwordController = TextEditingController();
final confirmPasswordController = TextEditingController();
...

2. Tambahkan properti controller pada TextFormField username untuk menghubungkan


TextFormField ke TextEditingController username.

create_account_screen.dart
...
child: TextFormField(
controller: usernameController,
...

3. Tambahkan properti controller pada TextFormField password untuk menghubungkan


TextFormField ke TextEditingController password.

create_account_screen.dart
...
child: TextFormField(
controller: passwordController,
...

4. Tambahkan properti controller pada TextFormField confirm password untuk


menghubungkan TextFormField ke TextEditingController confirm password.

36
create_account_screen.dart
...
child: TextFormField(
controller: confirmPasswordController,
...

7.2 Menampilkan dan Menyembunyikan Teks Password

1. Tambahkan 1 buah variabel isVisiblePassword dengan tipe data boolean. Nilai variabel
secara default bernilai false yang berarti teks pada password akan disembunyikan.

create_account_screen.dart
...
final passwordController = TextEditingController();

bool isVisiblePassword = false;


...

2. Tambahkan properti obscureText pada TextFormField password yang berfungsi untuk


menampilkan atau menyembunyikan teks password.

create_account_screen.dart
...
child: TextFormField(
controller: passwordController,
obscureText: !isVisiblePassword,
...

3. Tambahkan perintah untuk menampilkan dan menyembunyikan teks password pada


IconButton visibility yang terdapat pada TextFormField password.

create_account_screen.dart
...
hintText: "Password",
suffixIcon: IconButton(
onPressed: () {
setState(() {
isVisiblePassword = !isVisiblePassword;
});
},
icon: Icon(isVisiblePassword
? [Link]
: Icons.visibility_off),
),

37
...

7.3 Menampilkan dan Menyembunyikan Teks Confirm Password

1. Tambahkan 1 buah variabel isVisibleConfirmPassword dengan tipe data boolean. Nilai


variabel secara default bernilai false yang berarti teks pada confirm password akan
disembunyikan.

create_account_screen.dart
...
bool isVisiblePassword = false;
bool isVisibleConfirmPassword = false;
...

2. Tambahkan properti obscureText pada TextFormField confirm password yang berfungsi


untuk menampilkan atau menyembunyikan teks confirm password.

create_account_screen.dart
...
child: TextFormField(
controller: confirmPasswordController,
obscureText: !isVisibleConfirmPassword,
...

3. Tambahkan perintah untuk menampilkan dan menyembunyikan teks password pada


IconButton visibility yang terdapat pada TextFormField password.

create_account_screen.dart
...
hintText: "Password",
suffixIcon: IconButton(
onPressed: () {
setState(() {
isVisibleConfirmPassword = !isVisibleConfirmPassword;
});
},
icon: Icon(isVisibleConfirmPassword
? [Link]
: Icons.visibility_off),
),
...

38
4. Hasil untuk menampilkan atau menyembunyikan teks password dan teks confirm password.

7.4 Menambahkan Validasi Form

1. Tambahkan 1 buah variabel GlobalKey<FormState> untuk mengecek apakah semua input


pada form valid.

create_account_screen.dart
...
bool isVisibleConfirmPassword = false;

final formKey = GlobalKey<FormState>();


...

2. Tambahkan properti key pada widget Form.

create_account_screen.dart
...
child: Form(
key: formKey,
...

3. Tambahkan properti validator pada TextFormField username.

create_account_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "username is required";
}

39
return null;
},
...

4. Tambahkan properti validator pada TextFormField password.

create_account_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "password is required";
}
return null;
},
...

5. Tambahkan properti validator pada TextFormField confirm password.

create_account_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "confirm password is required";
} else if ([Link] != [Link]) {
return "Password don't match";
}
return null;
},
...

6. Setelah properti validator ditambahkan pada masing-masing TextFormField, selanjutnya


adalah melakukan pengecekan validasi pada button create account. tambahkan kode berikut
pada properti onPressed button create account.

create_account_screen.dart
...
onPressed: () {
if ([Link]!.validate()) {}
},
...

40
7. Hasil yang ditampilkan setelah validasi dibuat. Ketika button create account di tap
sedangkan username, password dan confirm password tidak diisi maka akan muncul pesan
validasi seperti gambar berikut.

8. Hasil yang ditampilkan jika password yang diisi tidak sama dengan confirm password, maka
akan muncul pesan validasi seperti gambar berikut.

7.5 Membuat Fungsi Create Account

1. Buat fungsi create account di dalam file database_helper.dart. Fungsi ini akan
memasukkan data pengguna baru ke dalam tabel users.

database_helper.dart
...
// Fungsi Create Account

41
Future<int> createAccount(UserModel user) async {
final Database db = await database;

return [Link]('users', [Link]());


}

2. Buat proses create account pada file create_account_screen.dart. Tambahkan beberapa


baris kode berikut di dalam class _CreateAccountState, pastikan lakukan import file
database_helper.dart, user_model.dart dan login_screen.dart. Proses yang dibuat
adalah; mengambil inputan userName dan userPassword dari pengguna, lalu dimasukkan
datanya ke dalam tabel users, menuggu hasil (result) berhasil atau tidak, jika berhasil
akan ditampilkan snackbar dengan pesan 'Account created successfully!', dan jika
tidak berhasil akan ditampilkan pesan 'Failed to create account. Please try
again.'.

create_account_screen.dart
import '../database/database_helper.dart';
import '../models/user_model.dart';
import 'login_screen.dart';
...

...
final formKey = GlobalKey<FormState>();

final db = DatabaseHelper();

// Fungsi Create Account


Future<void> createAccount() async {
try {
int result = await [Link](
UserModel(
userName: [Link],
userPassword: [Link],
),
);

if (!mounted) return;

if (result > 0) {
[Link](context).showSnackBar(
SnackBar(
content: Text('Account created successfully!'),

42
backgroundColor: [Link][400],
behavior: [Link],
),
);

// Navigasi ke halaman login


[Link](
context,
MaterialPageRoute(builder: (context) => const LoginScreen()),
);
} else {
[Link](context).showSnackBar(
const SnackBar(
content: Text('Failed to create account. Please try again.'),
backgroundColor: [Link],
behavior: [Link],
),
);
}
} catch (e) {
if (!mounted) return;

[Link](context).showSnackBar(
SnackBar(
content: Text('An error occurred while creating the account'),
backgroundColor: [Link],
behavior: [Link],
),
);
}
}
...

3. Panggil fungsi createAccount() pada button Create Account.

create_account_screen.dart
...
onPressed: () {
if ([Link]!.validate()) {
createAccount();
}
},
...

43
4. Setelah membuat fungsi create account selanjutnya adalah menguji proses create account
dengan mengisi username, password, dan confirm password, jika berhasil maka akan muncul
sebuah SnackBar dengan pesan “Account created successfully!” dan akan diarahkan
ke halaman login, dan jika gagal maka akan muncul sebuah SnackBar dengan pesan
“Failed to create account. Please try again.” seperti yang terlihat pada gambar
berikut.

7.6 Membuat Navigator TextButton Login

1. Tambahkan perintah pada TextButton login. Jika TextButton login di tap maka aplikasi
akan membuka halaman login.

create_account_screen.dart
...
TextButton(
onPressed: () {
[Link](
context,
MaterialPageRoute(
builder: (context) => const LoginScreen(),
),
);
},
child: const Text("Login"),
),
...

44
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 8 (Delapan)
Telp/Fax. 061 822 4051
[Link]

Ujian Tengah Semester

Materi Pembelajaran : 1. Soal UTS

Soal UTS

45
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 9 (Sembilan)
Telp/Fax. 061 822 4051
[Link]

Homepage

Materi Pembelajaran : 1. Desain User Interface Homepage

9.1 Desain User Interface Homepage

1. Tambahkan 1 buah folder di dalam folder lib dengan nama notes.


2. Tambahkan 1 buah file di dalam folder notes dengan nama notes_screen.dart.

3. Buat 1 buah class pada file notes_screen.dart dengan nama NotesScreen menggunakan
StatefulWidget, lalu tambahkan widget Scaffold sebagai struktur dasar halaman.
Tambahkan juga sebuah properti body pada widget Scaffold untuk menentukan konten
yang akan ditampilkan pada homepage (halaman notes).

notes_screen.dart
import 'package:flutter/[Link]';

class NotesScreen extends StatefulWidget {


const NotesScreen({[Link]});

@override
State<NotesScreen> createState() => _NotesScreenState();
}

class _NotesScreenState extends State<NotesScreen> {


@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text("Halaman Notes"),
),
);
}
}

46
4. Selanjutnya modifikasi fungsi login yang berada pada file login_screen.dart.
tambahkan perintah navigasi untuk membuka halaman Notes jika login berhasil.
login_screen.dart
...
import '../notes/notes_screen.dart';

...
// Navigasi ke halaman Notes jika login berhasil
[Link](
context,
MaterialPageRoute(
builder: (context) => const NotesScreen(),
),
);
...

5. Setelah melakukan modifikasi fungsi login, lakukan pengujian fungsi login dengan
cara mengisi username dan password dengan akun yang sudah terdaftar sebelumnya,
lalu tap button Login. Jika login berhasil maka aplikasi akan membuka halaman
Notes, seperti yang terlihat pada gambar berikut.

6. Jika sudah berhasil login selanjutnya desain user interface halaman Notes.
Tambahkan sebuah AppBar yang berisi title aplikasi dan terdapat sebuah icon untuk
logout seperti berikut.

47
notes_screen.dart
...
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: const Text("Notes App"),
actions: [
IconButton(
onPressed: () {},
icon: const Icon([Link]),
),
],
),
body: Center(
child: Text("Halaman Notes"),
),
);
...

7. Tambahkan sebuah button tambah dibawah widget AppBar


dengan jenis floatingActionButton yang akan digunakan
sebagai navigasi ke halaman tambah/buat note.
notes_screen.dart
...
floatingActionButton: FloatingActionButton(
backgroundColor: [Link],
onPressed: () {},
child: const Icon([Link]),
),
...

8. Tambahkan sebuah TextFormField untuk fitur pencarian notes seperti berikut.


notes_screen.dart
...
body: Padding(
padding: const [Link](top: 15),
child: Column(
children: [
// textfield pencarian

48
Container(
padding: const [Link](horizontal: 10),
margin: const [Link](horizontal: 10),
decoration: BoxDecoration(
color: [Link](.1),
borderRadius: [Link](6),
),
child: TextFormField(
decoration: const InputDecoration(
border: [Link],
hintText: "Search notes",
icon: Icon([Link])),
),
),
],
),
),
...

9. Menambahkan perintah pada button logout sehingga ketika button logout di tap
maka akan menutup halaman Notes dan membuka halaman login.
notes_screen.dart
import 'package:flutter/[Link]';
import '../auth/login_screen.dart';
...
...
IconButton(
onPressed: () {
[Link](
context,
MaterialPageRoute(
builder: (context) => const LoginScreen(),
),
// Hapus semua route sebelumnya
(route) => false,
);
},
icon: const Icon([Link]),
),
...

49
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 10 (Sepuluh)
Telp/Fax. 061 822 4051
[Link]

Fitur Create Data

1. Desain User Interface Halaman Create Data


Materi Pembelajaran :
2. Membuat Fungsi Create Data

10.1 Desain User Interface Halaman Create Data

Halaman create data berfungsi untuk membuat/menambahkan catatan ke dalam aplikasi


dengan menginput judul dan isi catatan lalu menekan/tap button yang akan disediakan untuk
melakukan proses penyimpanan ke dalam database (tabel notes). Lakukan langkah-langkah
berikut untuk membuatnya :

1. Tambahkan 1 buah file di dalam folder notes dengan nama create_note_screen.dart.

2. Buat 1 buah class pada file create_note_screen.dart dengan nama CreateNoteScreen


menggunakan StatefulWidget, lalu tambahkan widget Scaffold sebagai struktur dasar
halaman. Tambahkan juga sebuah properti body pada widget Scaffold untuk menentukan
konten yang akan ditampilkan pada halaman create data.

create_note_screen.dart
import 'package:flutter/[Link]';

class CreateNoteScreen extends StatefulWidget {


const CreateNoteScreen({[Link]});

@override
State<CreateNoteScreen> createState() => _CreateNoteScreenState();
}

class _CreateNoteScreenState extends State<CreateNoteScreen> {


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Create Note"),

50
),
body: const Center(
child: Text("Halaman Create Note"),
),
);
}
}
...

3. Selanjutnya modifikasi fungsi onPressed pada button add yang berada pada file
notes_screen.dart. Tambahkan perintah navigasi untuk membuka halaman create

data ketika button add di tap.


notes_screen.dart
...
import 'create_note_screen.dart';

...
floatingActionButton: FloatingActionButton(
onPressed: () {
[Link](
context,
MaterialPageRoute(
builder: (context) => const CreateNoteScreen(),
),
);
},
child: const Icon([Link]),
),
...

4. Setelah melakukan modifikasi pada button add dengan menambahkan perintah navigasi
untuk membuka halaman create data, lakukan pengujian dengan cara tap button add, jika
berhasil maka halaman create data akan dibuka.

51
5. Tambahkan sebuah IconButton check pada bagian AppBar yang
berfungsi untuk melakukan proses penyimpanan data ketika
IconButton di tap.

create_note_screen.dart
...
appBar: AppBar(
title: const Text("Create Note"),
actions: [
IconButton(
onPressed: () {},
icon: const Icon([Link]),
),
],
),
...

6. Modifikasi bagian body dengan menambahkan sebuah Form dan sebuah TextFormField
title untuk menginput judul Note.

create_note_screen.dart
...
body: Form(
child: Padding(
padding: const [Link](10.0),
child: Column(
crossAxisAlignment: [Link],

52
children: [
// TextFormField untuk input judul
TextFormField(
decoration: const InputDecoration(
labelText: "Title",
border: OutlineInputBorder(),
),
),
],
),
),
),
...

7. Selanjutnya tambahkan sebuah TextFormField content dibawah TextFormField title untuk


menginput isi Note.

create_note_screen.dart
...
const SizedBox(height: 10),
// TextField untuk input isi catatan/note
TextFormField(
maxLines: 5,
decoration: const InputDecoration(
labelText: "Content",
border: OutlineInputBorder(),
alignLabelWithHint: true,
),
),
...

10.2 Membuat Proses Create Data

Setelah tahap desain user interface halaman create data selesai, selanjutnya adalah
membuat agar aplikasi bisa melakukan proses penyimpanan data ke dalam database, lakukan
langkah-langkah berikut :

1. Tambahkan 2 buah TextEditingController di dalam class _CreateNoteScreenState


untuk mengontrol atau memantau teks yang diketik pada TextFormField title dan
TextFormField content.

53
create_note_screen.dart
...
class _CreateNoteScreenState extends State<CreateNoteScreen> {
final titleController = TextEditingController();
final contentController = TextEditingController();

@override
Widget build(BuildContext context) {
...

2. Tambahkan properti controller pada TextFormField title untuk menghubungkan


TextFormField ke TextEditingController title.

create_note_screen.dart
...
child: TextFormField(
controller: titleController,
...

3. Tambahkan properti controller pada TextFormField content untuk menghubungkan


TextFormField ke TextEditingController content.

create_note_screen.dart
...
child: TextFormField(
controller: contentController,
...

4. Tambahkan 1 buah variabel GlobalKey<FormState> untuk mengecek apakah semua input


pada form valid.

create_note_screen.dart
...
final contentController = TextEditingController();

final formKey = GlobalKey<FormState>();


...

5. Tambahkan properti key pada widget Form dengan value nama variabel
GlobalKey<FormState> yang telah dibuat sebelumnya.

create_note_screen.dart
...
body: Form(

54
key: formKey,
...

6. Tambahkan properti validator pada TextFormField title.

create_note_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "Title is required";
}
return null;
},
...

7. Tambahkan properti validator pada TextFormField content.

create_note_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "Content is required";
}
return null;
},
...

8. Setelah properti validator ditambahkan pada masing-masing TextFormField, selanjutnya


adalah melakukan pengecekan validasi pada IconButton check. tambahkan kode berikut
pada properti onPressed IconButton check.

create_note_screen.dart
...
onPressed: () {
if ([Link]!.validate()) {}
},
...

9. Hasil yang ditampilkan setelah validasi dibuat. Ketika IconButton check di tap sedangkan
title dan content tidak diisi maka akan muncul pesan validasi seperti gambar berikut.

55
10. Selanjutnya buat fungsi create note di dalam file database_helper.dart dengan
melakukan import file note_model.dart sebelumnya. Fungsi ini untuk menyimpan note
ke dalam tabel notes.

database_helper.dart
import '../models/note_model.dart';
...

...
// Create note method
Future<int> createNote(NoteModel note) async {
final Database db = await database;

return [Link]('notes', [Link]());


}
...

11. Buat proses create note pada file create_note_screen.dart. Tambahkan beberapa baris
kode berikut di dalam class _CreateNoteScreenState, pastikan lakukan import file
database_helper.dart dan note_model.dart.

create_note_screen.dart
...
import '../models/note_model.dart';
import '../database/database_helper.dart';
...
...
final formKey = GlobalKey<FormState>();

56
final db = DatabaseHelper();

Future<void> createNote() async {


try {
int result = await [Link](
NoteModel(
noteTitle: [Link],
noteContent: [Link],
createdAt: [Link]().toIso8601String(),
),
);

if (!mounted) return;

if (result > 0) {
[Link](context).showSnackBar(
SnackBar(
content: const Text('Note created successfully!'),
backgroundColor: [Link][400],
behavior: [Link],
),
);

// Navigasi ke halaman Notes


[Link](
context,
MaterialPageRoute(builder: (context) => const NotesScreen()),
);
} else {
[Link](context).showSnackBar(
const SnackBar(
content: Text('Failed to create note. Please try again.'),
backgroundColor: [Link],
behavior: [Link],
),
);
}
} catch (e) {
if (!mounted) return;

[Link](context).showSnackBar(

57
const SnackBar(
content: Text('An error occurred while creating the note.'),
backgroundColor: [Link],
behavior: [Link],
),
);
}
}
...

12. Selanjutnya panggil fungsi createNote() pada IconButton check.

create_note_screen.dart
...
IconButton(
onPressed: () {
if ([Link]!.validate()) {
createNote();
}
},
icon: const Icon([Link]),
),
...

13. Setelah selesai membuat proses create note, lakukan pengujian dengan cara mengisi
title dan content lalu tap IconButton check. Jika berhasil maka note akan disimpan
ke dalam database (tabel notes) dan aplikasi akan kembali ke halaman homepage
dan menampilkan SnackBar dengan pesan 'Note created successfully!'.

58
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 11 (Sebelas)
Telp/Fax. 061 822 4051
[Link]

Fitur Read Data

Materi Pembelajaran : 1. Membuat Fungsi Menampilkan Data

11.1 Membuat Fungsi Menampilkan Data

Pada tahap ini akan dilakukan pengembangan pada homepage dengan menampilkan
data (notes) yang telah ditambahkan ke dalam database. Lakukan langkah-langkah berikut untuk
membuatnya :

1. Buat fungsi untuk mengambil data dari tabel notes pada class DatabaseHelper yang
berada di dalam file database_helper.dart.
database_helper.dart
...
// Get notes method
Future<List<NoteModel>> getNotes() async {
final db = await database;
final result = await [Link]('notes');

return [Link]((e) => [Link](e)).toList();


}

2. Lakukan modifikasi pada file note_screen.dart. Lakukan import beberapa file yang
dibutuhkan seperti berikut.

note_screen.dart
import 'package:flutter/[Link]';
import '../auth/login_screen.dart';
import 'package:intl/[Link]';
import '../database/database_helper.dart';
import '../models/note_model.dart';
import 'create_note_screen.dart';
...

3. Tambahkan beberapa baris kode berikut pada class _NotesScreenState.

59
note_screen.dart
...
class _NotesScreenState extends State<NotesScreen> {
late DatabaseHelper handler;
late Future<List<NoteModel>> notes;

@override
void initState() {
[Link]();
handler = DatabaseHelper();
notes = [Link]();
}
...

4. Selanjutnya menampilkan data (notes) dibawah TextFormField pencarian. Tambahkan


beberapa baris kode berikut.

note_screen.dart
...
Expanded(
child: FutureBuilder<List<NoteModel>>(
future: notes,
builder: (BuildContext context,
AsyncSnapshot<List<NoteModel>> snapshot) {
if ([Link] == [Link]) {
return const Center(child: CircularProgressIndicator());
} else if ([Link]) {
return Center(child: Text('Error: ${[Link]}'));
} else if (![Link] || [Link]!.isEmpty) {
return const Center(child: Text("No Data"));
} else {
final items = [Link]!;
return [Link](
itemCount: [Link],
padding: const [Link](8),
itemBuilder: (context, index) {
final note = items[index];
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: [Link],
margin: const [Link](vertical: 6),
child: Card(

60
shape: RoundedRectangleBorder(
borderRadius: [Link](6),
),
elevation: 4,
shadowColor: [Link](0.5),
child: ListTile(
contentPadding: const [Link](
horizontal: 16, vertical: 6),
title: Text(
[Link],
style: const TextStyle(
fontWeight: [Link], fontSize: 16),
),
subtitle: Text(
DateFormat("yMMMd")
.format([Link]([Link])),
style: const TextStyle(
color: [Link], fontSize: 13),
),
onTap: () {
// Navigasi ke halaman lihat/update note
},
),
),
);
},
);
}
},
),
),
...

5. Setelah fungsi untuk menampilkan data (notes) selesai


ditambahkan, maka homepage sekarang sudah dapat menampilkan
notes yang sudah ditambahkan sebelumnya seperti yang terlihat
pada gambar berikut.

61
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 12 (Dua Belas)
Telp/Fax. 061 822 4051
[Link]

Fitur Update Data

1. Desain User Interface Halaman Update Data


Materi Pembelajaran :
2. Membuat Fungsi Update Data

12.1 Desain User Interface Halaman Update Data

Halaman update data berfungsi untuk menampilkan catatan secara detail dan untuk
melakukan perubahan catatan. Lakukan langkah-langkah berikut untuk membuatnya :

1. Tambahkan 1 buah file di dalam folder notes dengan nama update_note_screen.dart.

2. Buat 1 buah class pada file update_note_screen.dart dengan nama


UpdateNoteScreen menggunakan StatefulWidget, lalu tambahkan widget Scaffold
sebagai struktur dasar halaman. Tambahkan juga sebuah properti body pada widget
Scaffold untuk menentukan konten yang akan ditampilkan pada halaman update data.

update_note_screen.dart
import 'package:flutter/[Link]';

class UpdateNoteScreen extends StatefulWidget {


const UpdateNoteScreen({[Link]});

@override
State<UpdateNoteScreen> createState() => _UpdateNoteScreenState();
}

class _UpdateNoteScreenState extends State<UpdateNoteScreen> {


@override
Widget build(BuildContext context) {
return const Center(
child: Text("Halaman Update Note"),
);
}

62
}

3. Selanjutnya modifikasi fungsi onTap pada widget ListTile yang berada pada file
notes_screen.dart. Tambahkan perintah navigasi untuk membuka halaman update data
ketika ListTile di tap.

note_screen.dart
...
import 'update_note_screen.dart';

...
onTap: () {
// Navigasi ke halaman lihat/update note
[Link](
context,
MaterialPageRoute(
builder: (context) => UpdateNoteScreen(),
),
);
},
...

4. Setelah melakukan modifikasi pada widget ListTile dengan menambahkan perintah


navigasi untuk membuka halaman update data, lakukan pengujian dengan cara tap note
yang sudah ditampilkan, jika berhasil maka halaman update data akan dibuka.

63
5. Tambahkan sebuah IconButton check pada bagian AppBar yang berfungsi untuk
melakukan proses penyimpanan data ketika IconButton di tap.

update_note_screen.dart
...
appBar: AppBar(
title: const Text("Update Note"),
actions: [
IconButton(
onPressed: () {},
icon: const Icon([Link]),
),
],
),
...

6. Modifikasi bagian body dengan menambahkan sebuah Form dan sebuah TextFormField
untuk menampilkan title dan content note.

update_note_screen.dart
...
body: Form(
child: Padding(
padding: const [Link](10.0),
child: Column(
crossAxisAlignment: [Link],
children: [
const SizedBox(height: 5),
// TextField untuk input judul
TextFormField(
decoration: const InputDecoration(
labelText: "Title",
border: OutlineInputBorder(),
),
),
const SizedBox(height: 10),
// TextField untuk input isi catatan/note
TextFormField(
maxLines: 5,
decoration: const InputDecoration(
labelText: "Content",

64
border: OutlineInputBorder(),
alignLabelWithHint: true,
),
),
],
),
),
),
...

12.2 Membuat Proses Update Data

Setelah tahap desain user interface halaman update data selesai, selanjutnya adalah
membuat agar aplikasi bisa melakukan proses update data ke dalam database, lakukan
langkah-langkah berikut :

1. Tambahkan sebuah variabel instans dengan nama note yang menggunakan tipe data
NoteModel di dalam class UpdateNoteScreen. Kemudian tambahkan parameter pada
konstruktor UpdateNoteScreen.

update_note_screen.dart
import 'package:flutter/[Link]';
import '../models/note_model.dart';

class UpdateNoteScreen extends StatefulWidget {


final NoteModel note;

const UpdateNoteScreen({[Link], required [Link]});


...

2. Selanjutnya modifikasi navigasi untuk ke halaman update data yang berada pada file
notes_screen.dart dengan menambahkan argumen note seperti berikut.

note_screen.dart
...
[Link](
context,
MaterialPageRoute(
builder: (context) =>
UpdateNoteScreen(note: note),
),

65
);
...

3. Tambahkan 2 buah TextEditingController di dalam class _UpdateNoteScreenState


untuk mengontrol atau memantau teks yang diketik pada TextFormField title dan
TextFormField content.

update_note_screen.dart
...
class _UpdateNoteScreenState extends State<UpdateNoteScreen> {
late TextEditingController titleController;
late TextEditingController contentController;
...

4. Tambahkan properti controller pada TextFormField title untuk menghubungkan


TextFormField ke TextEditingController title.

update_note_screen.dart
...
TextFormField(
controller: titleController,
...

5. Tambahkan properti controller pada TextFormField content untuk menghubungkan


TextFormField ke TextEditingController content.

update_note_screen.dart
...
TextFormField(
controller: contentController,
...

6. Tambahkan 1 buah variabel GlobalKey<FormState> untuk mengecek apakah semua


input pada form valid.

update_note_screen.dart
...
late TextEditingController contentController;

final formKey = GlobalKey<FormState>();


...

66
7. Tambahkan properti key pada widget Form dengan value nama variabel
GlobalKey<FormState> yang telah dibuat sebelumnya.

update_note_screen.dart
...
body: Form(
key: formKey,
...

8. Tambahkan properti validator pada TextFormField title.

update_note_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "Title is required";
}
return null;
},
...

9. Tambahkan properti validator pada TextFormField content.

update_note_screen.dart
...
validator: (value) {
if (value!.isEmpty) {
return "Content is required";
}
return null;
},
...

10. Setelah properti validator ditambahkan pada masing-masing TextFormField,


selanjutnya adalah melakukan pengecekan validasi pada IconButton check. tambahkan
kode berikut pada properti onPressed IconButton check.

update_note_screen.dart
...
onPressed: () {
if ([Link]!.validate()) {}
},
...

67
11. Selanjutnya buat fungsi update note di dalam file database_helper.dart. Fungsi ini
untuk merubah catatan (note) yang ada pada tabel notes berdasarkan noteId.

database_helper.dart
...
// Update note method
Future<int> updateNote(String title, String content, int noteId) async
{
final Database db = await database;
return [Link](
'notes',
{
'noteTitle': title,
'noteContent': content,
},
where: 'noteId = ?',
whereArgs: [noteId],
);
}
...

12. Buat proses update data pada file update_note_screen.dart. Tambahkan beberapa
baris kode berikut di dalam class _UpdateNoteScreenState, pastikan lakukan import
file database_helper.dart dan notes_screen.dart.

update_note_screen.dart
...
import '../database/database_helper.dart';
import 'notes_screen.dart';
...
...
final formKey = GlobalKey<FormState>();

final db = DatabaseHelper();

@override
void initState() {
[Link]();
titleController = TextEditingController(text:
[Link]);

68
contentController = TextEditingController(text:
[Link]);
}

Future<void> updateNote() async {


try {
int result = await [Link](
[Link],
[Link],
[Link]!,
);

if (!mounted) return;

if (result > 0) {
[Link](context).showSnackBar(
SnackBar(
content: Text('Note updated successfully!'),
backgroundColor: [Link][400],
behavior: [Link],
),
);
[Link](
context,
MaterialPageRoute(builder: (context) => const NotesScreen()),
);
} else {
[Link](context).showSnackBar(
const SnackBar(
content: Text('Failed to update note. Please try again.'),
backgroundColor: [Link],
behavior: [Link],
),
);
}
} catch (e) {
if (!mounted) return;
[Link](context).showSnackBar(
const SnackBar(
content: Text('An error occurred while updating the note.'),

69
backgroundColor: [Link],
behavior: [Link],
),
);
}
}
...

13. Selanjutnya panggil fungsi updateNote() pada IconButton check.

update_note_screen.dart
...
IconButton(
onPressed: () {
if ([Link]!.validate()) {
updateNote();
}
},
icon: const Icon([Link]),
),
...

14. Setelah selesai membuat proses update data, lakukan pengujian dengan cara tap pada
catatan (note) yang ingin dirubah, Selanjutnya lakukan perubahan isi title atau content
lalu tap IconButton check. Jika berhasil maka note akan disimpan ke dalam database
(tabel notes) dan aplikasi akan kembali ke halaman homepage dan menampilkan
SnackBar dengan pesan “Note updated successfully!”.

70
71
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 13 (Tiga Belas)
Telp/Fax. 061 822 4051
[Link]

Fitur Delete Data

1. Desain User Interface Delete Data


Materi Pembelajaran :
2. Membuat Fungsi Delete Data

13.1 Desain User Interface Delete Data

Pada tahap ini aplikasi akan dikembangkan dengan menambahkan fitur untuk menghapus
data. Untuk desain user interface aplikasi, akan ditampilkan sebuah icon delete dan sebuah jendela
dialog yang berisi pesan konfirmasi keyakinan untuk menghapus data. Lakukan langkah-langkah
berikut untuk membuatnya :

1. Modifikasi file note_screen.dart. Tambahkan properti trailing


pada widget ListTile, lalu buat sebuah IconButton Delete di
dalamnya agar IconButton ditempatkan disisi kanan.

note_screen.dart
...
trailing: IconButton(
onPressed: () {},
icon: const Icon(
[Link],
color: [Link],
),
),
...

2. Buat fungsi untuk menampilkan jendela konfirmasi di dalam class _NotesScreenState agar
data tidak langsung terhapus.

note_screen.dart
...
void showDeleteDialog(BuildContext context, int noteId) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Delete Note?'),
content: const Text('Are you sure you want to delete this note?'),

72
actions: [
TextButton(
onPressed: () => [Link](context),
child: const Text('Cancel'),
),
TextButton(
onPressed: () {
[Link](context);
},
child: const Text(
'Delete',
style: TextStyle(color: [Link]),
),
),
],
),
);
}
...

3. Selanjutnya panggil fungsi showDeleteDialog() pada IconButton Delete. Jika berhasil maka
aplikasi akan menampilkan jendela konfirmasi seperti gambar berikut ketika IconButton
Delete di tap.

note_screen.dart
...
trailing: IconButton(
onPressed: () {
showDeleteDialog(
context, items[index].noteId!);
},
icon: const Icon(
[Link],
color: [Link],
),
),
...

73
13.2 Membuat Proses Delete Data

Setelah tahap desain user interface delete data selesai, selanjutnya adalah membuat agar
aplikasi bisa melakukan proses delete data yang ada di database, lakukan langkah-langkah berikut.

1. Selanjutnya buat fungsi delete note di dalam file database_helper.dart. Fungsi ini untuk
menghapus catatan (note) yang ada pada tabel notes berdasarkan noteId.
database_helper.dart
...
// Delete notes method
Future<int> deleteNote(int id) async {
final Database db = await database;
return [Link](
'notes',
where: 'noteId = ?',
whereArgs: [id],
);
}
...

2. Buat proses delete data di dalam properti onPressed widget TextButton Delete. Tambahkan
beberapa baris kode berikut.

note_screen.dart
...
onPressed: () async {
[Link](context);

int result = await [Link](noteId);


if (!mounted) return;

if (result > 0) {
setState(() {
notes = [Link]();
});

[Link](context).showSnackBar(
SnackBar(
content: const Text('Note deleted successfully!'),
backgroundColor: [Link][400],

74
behavior: [Link],
),
);
} else {
[Link](context).showSnackBar(
const SnackBar(
content: Text('Failed to delete note. Please try again.'),
backgroundColor: [Link],
behavior: [Link],
),
);
}
},
...

3. Setelah selesai membuat proses delete data, lakukan pengujian dengan cara tap IconButton
delete pada data yang ingin dihapus, Selanjutnya pada jendela konfirmasi pilih Delete. Jika
berhasil maka note akan dihapus dari database dan aplikasi akan me-refresh halaman homepage
dan menampilkan SnackBar dengan pesan “Note deleted successfully!”.

75
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 14 (Empat Belas)
Telp/Fax. 061 822 4051
[Link]

Fitur Search Data

Materi Pembelajaran : 1. Membuat Fungsi Search Data

14.1 Membuat Proses Search Data

Pada tahap ini aplikasi akan dikembangkan dengan menambahkan proses untuk pencarian
data dengan cara mengisi title atau content yang ingin dicari pada TextFormField pencarian yang
telah dibuat sebelumnya. Lakukan langkah-langkah berikut untuk membuatnya :

1. Tambahkan fungsi search note di dalam file database_helper.dart. Fungsi ini untuk
mengambil catatan (note) yang ada pada tabel notes berdasarkan keyword pencarian judul dan
isi catatan yang diberikan oleh pengguna.

database_helper.dart
...
// Search notes method
Future<List<NoteModel>> searchNotes(String keyword) async {
final Database db = await database;

final List<Map<String, Object?>> result = await [Link](


'notes',
where: 'LOWER(noteTitle) LIKE ? OR LOWER(noteContent) LIKE ?',
whereArgs: ['%${[Link]()}%', '%${[Link]()}%'],
);

return [Link]((map) => [Link](map)).toList();


}
...

2. Tambahkan controller untuk TextFormField pencarian.

note_screen.dart
...
final TextEditingController _searchController = TextEditingController();
String _searchKeyword = '';
...

76
3. Tambahkan properti controller pada TextFormField pencarian dengan value
TextEditingController yang telah dibuat sebelumnya.

note_screen.dart
...
child: TextFormField(
controller: _searchController,
...

4. Tambahkan properti onChanged pada TextFormField pencarian agar responsif, yaitu data yang
ditampilkan sesuai dengan apa yang dicari, dan jika tidak ada data yang dicari maka akan
ditampilkan seluruh data.

note_screen.dart
...
onChanged: (value) {
setState(() {
_searchKeyword = [Link]();
if (_searchKeyword.isEmpty) {
notes = [Link]();
} else {
notes = [Link](_searchKeyword);
}
});
},
...

5. Setelah selesai membuat proses search data, lakukan pengujian dengan cara ketik keyword yang
ingin dicari pada textfield pencarian. Jika berhasil maka yang ditampilkan hanyalah data yang
mengandung unsur keyword yang ada pada textfield pencarian.

77
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 15 (Lima Belas)
Telp/Fax. 061 822 4051
[Link]

Deployment

Materi Pembelajaran : 1. Build APK (Android Package Kit)

15.1 Deployment
Setelah tahap pengembangan aplikasi selesai, langkah selanjutnya adalah deployment.
Proses ini dimulai dengan membangun (build) proyek aplikasi yang telah selesai dibuat menjadi
format yang bisa dijalankan di berbagai platform, seperti APK (Android Package Kit) atau
AAB (Android App Bundle) untuk Android, dan IPA (iOS App Store Package) untuk iOS.
File-file inilah yang nantinya akan didistribusikan melalui Google Play Store atau App Store,
atau langsung diinstal pada perangkat Android/iOS.

15.2 Build APK (Android Package Kit)


Flutter punya kemampuan untuk mengubah project yang sudah kita buat menjadi
berkas .apk, sehingga aplikasi yang telah dibuat bisa berjalan di perangkat Android. Proses
Build APK ini adalah langkah untuk mengubah aplikasi Flutter ke dalam format .apk yang siap
diinstal di ponsel atau tablet Android. Berikut adalah tahapan untuk melakukan build aplikasi
Flutter menjadi APK.
1. Sebelum melakukan build apk lakukan pengaturan informasi mengenai aplikasi pada file
[Link]. Buka file [Link] yang berada pada lokasi
android/app/src/main/[Link].

[Link]
...
<application
android:label="NotesApp"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
...

2. Ubah icon aplikasi yang secara default adalah icon flutter dengan cara mengganti gambar
icon “ic_launcher.png” dengan berbagai ukuran resolusi yang berada pada folder
android/app/src/main/res/. Sebelumnya buat icon yang akan digunakan terlebih dahulu,
misal menggunakan Android Asset Studio melalui link

78
[Link] kemudian pilih Launcher icon
generator dan desain icon, misal icon seperti berikut.

3. Download icon yang sudah dibuat kemudian lakukan unzip berkas yang telah didownload.
Hasilnya adalah akan dibuatkan icon dengan beberapa ukuran resolusi (mipmap).
Selanjutnya copy isi folder res ke dalam android/app/src/main/res/ seperti berikut.

4. Setelah selesai mengatur nama dan icon aplikasi, langkah selanjutnya adalah mengubah
aplikasi kita menjadi format APK. Penting untuk diketahui bahwa secara umum ada 2 mode
aplikasi yang berbeda: debug dan release. APK debug biasanya digunakan untuk
pengujian internal dan pengembangan. Mode ini aktif secara default saat menjalankan
aplikasi dengan perintah flutter run. Dan untuk aplikasi yang siap dirilis ke Google Play
Store, Anda perlu membuat APK release. Mode ini dioptimalkan untuk performa dan
ukuran. Dan pada materi ini hanya membahas mode debug, caranya adalah buka jendela
terminal pada text editor kemudian jalankan perintah berikut.

79
flutter clean
flutter pub get
flutter build apk --debug

Perintah Fungsi
flutter clean Membersihkan cache dan hasil build sebelumnya
flutter pub get Mengunduh dan menginstal dependency dari [Link]
flutter build apk
Membangun file APK untuk Android dalam mode debug
--debug

5. Setelah proses build APK selesai akan ditampilkan informasi seperti berikut pada jendela
terminal.
√ Built build\app\outputs\flutter-apk\[Link].

6. Selanjutnya kirim file [Link] ke perangkat android lalu instal. Jika berhasil maka
aplikasi akan terpasang pada perangkat android tersebut.

80
STMIK TRIGUNA DHARMA
Jl. Jend. AH Nasution
No. 73 F Medan
Pertemuan 16 (Enam Belas)
Telp/Fax. 061 822 4051
[Link]

Ujian Akhir Semester

Materi Pembelajaran : 1. Soal UAS

16.1 Soal UAS

81

Anda mungkin juga menyukai