- Stateless Widget Adalah sebuah widget yang bersifat statis (tidak berubah). Stateless Widget bekerja dengan konsep Constructor -> Build. Konsep ini berarti widget langsung mengarahkan object untuk Build tanpa memiliki perantara untuk pengolahan variabel di dalam prosesnya.
- Stateful Widget Adalah sebuah widget yang bersifat dinamis. Widget dapat merubah tampilan sesuai respon dari tindakan yang dilakukan oleh user maupun perubahan berdasarkan operasi yang ada di dalam widget itu sendiri. Stateful Widget bekerja dengan konsep Constructor -> Internal State -> Build, artinya terdapat perantara berupa sebuah data maupun variabel yang disebut sebagai state (bersifat dinamis). State tersebut akan diolah dan disesuaikan kemudian ditampilkan saat Build.
Stateless Widget | Stateful Widget |
---|---|
Bersifat statis | Bersifat dinamis |
Tampilan tetap (tidak berubah) | Tampilan menyesuaikan interaksi user |
Alur: Contructor -> Build | Alur: Constructor -> Internal State -> Build |
Lebih ringan dirender | Memerlukan waktu reload render |
Cocok untuk widget tanpa perubahan data di dalamnya | Diperlukan untuk menyusun widget dengan pengolahan data yang interaktif |
Widget | Fungsi |
---|---|
CounterSeven | Inisiasi aplikasi |
CounterPage | Menampilkan counter dan button serta logicnya |
MaterialApp | Inisiasi title, theme, dan mengatur home dari aplikasi |
ThemeData | Mengatur tema yang digunakan |
Scaffold | Mengatur layout dari widget yang ada di dalamnya |
AppBar | Menambahkan bar aplikasi yang berisi title dengan align left |
Text | Berisi sebuah Text dengan properti di dalamnya |
Center | Mengatur layout widget di dalamnya agar centered |
Column | Mengatur layout widget di dalamnya agar turun ke bawah (tidak inline-flex) |
TextStyle | Mengatur style dari sebuah text |
Container | Menampung beberapa widget di dalamnya |
Row | Mengatur layout widget di dalamnya agar menyamping (inline-flex) |
FloatingActionButton | Membuat tombol yang dapat dimodifikasi event di dalamnya |
Icon | Menampilkan icon yang dibutuhkan sesuai propertinya |
const | final |
---|---|
Const dapat digunakan untuk deklarasi variabel immutable yang nilainya bersifat konstan. Setiap kali perlakuan render tetap dapat terinisiasi ulang sesuai nilainya sehingga lebih fleksibel pada keadaan yang memerlukan render data. Akan tetapi, tetap saja const tidak dapat diubah saat berada di runtime satu kali cycle program. | Final berarti single-assignment, sebuah final variabel perlu diinisiasi, sekalinya diinisiasi, nilai variabel tidak dapat diubah. Final dapat dimanfaatkan untuk meletakkan data-data yang tidak akan berubah sekalipun ada rendering (reload) |
- Membuat aplikasi Flutter bernama counter_7 dengan command
flutter create counter_7
- Menambahkan modules dari import flutter package dan fungsi main() yang dieksekusi pertama kali oleh Flutter pada main.dart
- Mengarahkan runApp() menuju aplikasi terkait 'CounterSeven'
- Menyusun CounterSeven sebagai StatelessWidget dan menambahkan MaterialApp widget untuk menginisiasikan hal-hal penting yang ditampilkan dalam aplikasi
- Mengarahkan home: menuju halaman CounterPage yang sudah diimport dari directory /pages/CounterPage.dart
- Menyusun CounterPage sebagai StatefulWidget dengan beberapa atributnya seperti judul dan key. Kemudian menambahkan state _CounterState() ke dalam widget untuk menyimpan internal state dari nilai _counter
- Menyusun _CounterState sebagai widget yang digunakan untuk menampilkan hasil counter
- Menginisiasikan _counter = 0 untuk state awal, lalu menambahkan dua fungsi _decrementCounter() dan _incrementCounter() yang digunakan untuk mengeset state menuju nilai yang diinginkan, yaitu -1 untuk _decrementCounter() dan +1 untuk _incrementCounter()
- Menyusun widget dengan Scaffold yang digunakan untuk menyimpan beberapa widget lain di dalamnya
- Menambahkan title pada Widget AppBar dan mengatur alignment dari title tersebut
- Menambahkan body dengan Widget Center untuk meletakkan child widget ke tengah
- Children widget pada body berisi Widget Text yang digunakan untuk menampilkan "GANJIL" vs "GENAP" sesuai kondisi nilai _counter saat ini beserta dengan TextStylenya. Jika _counter % 2 == 0 maka tampilkan blok "GENAP", sebaliknya tampilkan blok "GANJIL"
- Menambahkan dua button yaitu decrement & increment button menggunakan Widget FloatingActionButton yang disimpan dalam Widget Row (inline-flex posisi dari buttonya) di dalam Container.
- Mengarahkan atribut onPressed: pada button ke fungsi yang sesuai setStatenya, decrement button ke _decrementCounter dan increment button ke _incrementButton
- Menambahkan ikon ke button sesuai dengan permintaan soal, ikon negatif (Icons.remove) dan ikon plus (Icons.add)
BONUS
Menambahkan alur logika dari button decrement. Jika _counter > 0 maka tampilkan FloatingActionButton decrement, jika tidak maka tampilkan SizedBox() (widget kosong) untuk menghilangkan button saat nilai _counter <= 0
- Navigator.pushReplacement
Navigator ini akan menimpa halaman sekarang dengan halaman baru - Navigator.push
Navigator ini akan menambahkan rute lain ke atas tumpukan screen stack saat ini
Widget | Fungsi |
---|---|
Drawer | Membuat drawer navigator |
ListTile | Membuat list beberapa tile |
MaterialPageRoute | Mengarahkan routing ke halaman (widget) tertentu |
FormBudgetPage | Widget buatan sendiri untuk menampilkan halaman form |
OutlineInputBorder | Menambahkan border pada input |
InputDecoration | Menambahkan dekorasi input |
ButtonStyle | Menambahkan style button |
SnackBar | Menampilkan SnackBar |
SingleChildScrollView | Menyusun scroll type dari suatu body |
Card | Membuat card |
TextFormField | Membuat input field |
DropdownButtonFormField | Membuat dropdown sesuai validasi input |
Spacer | Membuat space fleksibel |
Event | Penjelasan |
---|---|
onPressed | Event yang terjadi ketika user telah selesai menekan |
onTap | Event yang terjadi ketika sesaat setelah klik |
onChanged | Event yang terjadi ketika ada perubahan |
Navigator bekerja selayaknya sebuah stack yang memiliki paradigma LIFO yaitu Last In First Out. Stack ini diterapkan pada layar untuk menampilkan layar dengan cara "PUSH" dan layar yang ditampilkan tersebut merupakan "TOP OF STACK", sedangkan layar sebelumnya berada di bawah dari "TOP OF STACK" dan seterusnya selama proses "PUSH" dan "POP" terjadi.
- Menambahkan Drawer menu pada app counter_7
- Drawer disusun dengan memiliki 3 menu yaitu CounterPage, FormBudgetPage, dan ShowBudgetPage
- Membuat 2 file yang belum ada di dalam Drawer yaitu FormBudgetPage dan ShowBudgetPage
- Menyusun halaman FormBudgetPage
- Menambahkan input dengan tipe data String bernama judul
- Menambahkan input dengan tipe data integer bernama nominal
- Menambahkan elemen dropdown untuk menyeleksi "Pengeluaran/Pemasukan"
- Menambahkan button untuk menyimpan budget
BONUS
Menambahkan date picker- Menambahkan toast saat tombol simpan diklik
- Menyusun halaman ShowBudgetPage
BONUS
Refactoring widget- Widget Budget masuk ke dalam components untuk menyimpan Budget dan sebagai kerangkanya
- Mengambil data dari Budget ke dalam ShowBudgetPage
- Menyusun card dan style untuk membedakan pengeluaran dan pemasukan
- Icons Flutter Class
https://api.flutter.dev/flutter/material/Icons-class.html - Dart Playground
https://dartpad.dev/?
Apakah bisa kita melakukan pengambilan data JSON tanpa membuat model terlebih dahulu? Jika iya, apakah hal tersebut lebih baik daripada membuat model sebelum melakukan pengambilan data JSON?
Pengambilan data JSON tanpa membuat model terlebih dahulu dapat dilakukan, nantinya data masih dalam wujud jsonDecode var data = jsonDecode(utf8.decode(response.bodyBytes));
. Namun, hal ini tidak lebih baik dibanding membuat model terlebih dahulu sebelum pengambilan data JSON karena data tidak langsung diinisiasi menjadi suatu object sesuai class modelnya.
Widget | Fungsi |
---|---|
MyWatchlistPage | Membuat halaman utama dari watchlist |
SingleWatchlistPage | Membuat halaman detail dari suatu watchlist |
FutureBuilder | Merupakan widget yang digunakan untuk melakukan proses asinkron |
Checkbox | Menampilkan Checkbox yang bisa diklik |
MaterialPageRoute | Mengarahkan routing ke halaman (widget) tertentu |
Drawer | Membuat drawer navigator |
ListTile | Membuat list beberapa tile |
Scaffold | Mengatur layout dari widget yang ada di dalamnya |
AppBar | Menambahkan bar aplikasi yang berisi title dengan align left |
Text | Berisi sebuah Text dengan properti di dalamnya |
Center | Mengatur layout widget di dalamnya agar centered |
Column | Mengatur layout widget di dalamnya agar turun ke bawah (tidak inline-flex) |
TextStyle | Mengatur style dari sebuah text |
Container | Menampung beberapa widget di dalamnya |
- JSON ditampilkan di halaman asal proyek MyWatchlist di
https://pbp-assignment-eugeniusms.herokuapp.com/mywatchlist/json/
- JSON difetch ke dalam fetch.dart sesuai urlnya dengan header
"Access-Control-Allow-Origin": "*", "Content-Type": "application/json"
- JSON yang telah difetch akan disesuaikan bodynya menuju model Watchlist sesuai dengan properti-properti
- Data list dalam model Watchlist dipanggil dalam MyWatchlistPage untuk distyling card satu per satu
- Setiap card memiliki onTap() yang jika diklik maka data object Watchlist pada card tersebut dipassing ke SingleWatchlistPage untuk ditampilkan khusus pada data tersebut
- Menambahkan ListTile() menuju MyWatchlistPage di dalam Drawer.dart
- Membuat file model mywatchlist bernama watchlist.dart yang berisi model dari Watchlist
class Watchlist { Watchlist({ required this.id, required this.watched, required this.title, required this.rating, required this.release_date, required this.review, });
- Melakukan fetch di dalam
utils/fetch.dart
ke alamat'https://pbp-assignment-eugeniusms.herokuapp.com/mywatchlist/json/'
- Menambahkan inisiasi class sesuai dengan JSON yang akan difetch
factory Watchlist.fromJson(Map<String, dynamic> json) => Watchlist( id: json["pk"], watched: json["fields"]["watched"], title: json["fields"]["title"], rating: json["fields"]["rating"], release_date: json["fields"]["release_date"], review: json["fields"]["review"], );
- Menambahkan object yang difetch ke dalam Flutter list di dalam fetch.dart
List<Watchlist> listWatchlist = []; for (var d in data) { if (d != null) { listWatchlist.add(Watchlist.fromJson(d)); } }
- Menyusun halaman MyWatchlistPage agar berisi daftar film sesuai isi elemen dari listWatchlist
BONUS
Menambahkan checkbox pada cardCheckbox( value: snapshot.data![index].watched, onChanged: (bool? value) { setState(() { this.value = snapshot.data![index].watched ? false : true; }); }, ),
BONUS
Menambahkan colored outline borderborder: Border.all( color: snapshot.data![index].watched ? Colors.green : Colors.red, width: 5 ),
- Menambahkan halaman detail
SingleWatchlistPage
dengan cara passing object Watchlist as a data ke widget SingleWatchlistPage untuk ditampilkan sesuai objectnya dengan properti-propertinyafinal Watchlist data; SingleWatchlistPage({required this.data});
- Melakukan styling di halaman detail
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
For help getting started with Flutter development, view the online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.