-
Stateless Widget
-
Stateless Widget adalah widget yang tidak menyimpan state (keadaan) internal. Artinya, ketika widget ini dibuat, widget tidak akan berubah. Stateless Widget bersifat final dan hanya menerima parameter yang diberikan pada saat pembuatan. Stateless widget lebih sering digunakan untuk menampilkan informasi statis atau elemen yang tidak memerlukan update.
-
Contoh penggunaan stateless widget: membuat teks statis, gambar, ikon, dll
-
-
Stateful Widget
- Stateful Widget adalah widget yang memiliki state internal yang dapat berubah. Stateful Widget bisa menyimpan informasi dan mengupdate tampilan berdasarkan perubahan yang terjadi selama life cycle aplikasi. Stateful Widget menggunakan dua kelas: kelas utama turunan dari StatefulWidget dan kelas State yang bertanggung jawab untuk menyimpan state dan mengelola update tampilan.
- Contoh pengunaan stateful widget: tombol yang dapat ditekan (untuk mengubah status), form input yang menyimpan data, elemen interaktif lainnya
-
Perbandingan stateless widget dan stateful widget
Aspek Stateless Widget Stateful Widget Definisi Widget yang tidak menyimpan state dan tidak dapat berubah setelah dibuat Widget yang menyimpan state dan dapat berubah seiring interaksi dengan user. Kelas Turunan dari StatelessWidget. Turunan dari StatefulWidget dan memiliki kelas State. Pembaharuan Tidak dapat mengupdate tampilan setelah dibangun. Dapat mengupdate tampilan menggunakan metode setState(). Penggunaan Cocok untuk elemen statis seperti teks, ikon, gambar. Cocok untuk elemen interaktif seperti tombol, form, atau sign in. Siklus Hidup Hanya memiliki satu life cycle. Memiliki dua life cycle: widget life cycle dan state life cycle. Kompleksitas Lebih sederhana dan lebih mudah digunakan. Lebih kompleks karena memerlukan manajemen state.
Widget | Fungsi |
---|---|
Scaffold | Menyediakan struktur dasar halaman, termasuk AppBar, body, dan elemen lain di dalam aplikasi. |
AppBar | Menampilkan bagian atas aplikasi yang berisi judul dan elemen lainnya |
Text | Menampilkan teks dalam aplikasi. Pada aplikasi ini digunakan untuk menampilkan judul aplikasi dan teks |
Padding | Memberikan jarak (padding) di sekeliling widget anaknya |
Column | Menyusun widget secara vertikal. |
Row | Menyusun widget secara horizontal. |
SizedBox | Memberikan ruang kosong di antara widget. Digunakan untuk memberikan jarak vertikal antar elemen. |
Center | Meletakkan widget child di dalam area untuk menempatkan child di tengah area widget. |
GridView.count | Menyusun widget anak dalam bentuk grid. Dalam aplikasi ini digunakan untuk menampilkan ItemCard dalam 3 kolom. |
Card | Menampilkan informasi dalam bentuk kartu. |
Container | Memberikan space untuk widget dan mengatur ukuran, warna, dan padding dari widget di dalamnya. |
Material | Memberikan efek material pada widget dan penggunaan tema. |
InkWell | Menambahkan efek sentuh (touch effect) pada widget ketika diklik. |
SnackBar | Menampilkan pesan temporary di bagian bawah layar untuk memberikan feedback pada user. |
Icon | Menampilkan ikon grafis. |
setState() adalah fungsi yang dimiliki oleh kelas State untuk mengelola keadaan (state) dari widget dalam aplikasi. Ketika fungsi setState() dipanggil, fungsi tersebut akan memberitahu Flutter untuk melakukan rebuild widget yang menggunakan state tersebut.
-
Mengupdate UI Ketika keadaan suatu widget berubah (misal nilai variabel, hasil perhitungan, atau status interaksi User (seperti klik tombol)), maka setState() digunakan untuk memperbarui UI supaya memeproses perubahan tersebut. Flutter akan menjalankan kembali build() dari widget yang bersangkutan dan menghasilkan UI baru yang sesuai dengan state terbaru.
-
Mengoptimalkan Proses Rebuild Dengan menggunakan fungsi setState(), Flutter hanya akan merebuild widget yang berkaitan dengan state yang diubah, bukan seluruh widget tree sehingga membantu meningkatkan performa aplikasi.
Contoh:
setState(() {
// Perubahan pada state
counter++;
});
Ketika kita memanggil setState(), kita harus memberikan fungsi callback yang berisi logika untuk memperbarui state. Fungsi ini kemudian diambil oleh Flutter untuk memperbarui UI. Pada contoh ini, variabel counter merupakan bagian dari state yang dikelola. Dengan memanggil setState(), nilai counter akan diubah dan UI akan diperbarui dengan menggunakan nilai(state) yang baru.
-
const
const digunakan untuk mendeklarasikan konstanta yang diinisialisasi pada waktu kompilasi. Nilai yang diassign kepada variabel const harus diketahui sebelum program dijalankan. Variabel const bersifat immutable dan lebih efisien dalam penggunaan memori karena Flutter dapat melakukan optimasi dengan mengelola nilai yang sama hanya sekali dalam memori.
-
final
final digunakan untuk mendeklarasikan variabel yang hanya dapat diinisialisasi sekali, tapi nilainya tidak harus diketahui pada waktu kompilasi. Nilai dari variabel final dapat ditetapkan pada waktu runtime. Final bersifat immutable setelah diinisialisasi, tapi final memungkinkan re-assign nilai yang lebih fleksibel karena nilainya bisa ditentukan oleh ekspresi yang dijalankan saat program berjalan.
-
Perbedaan const dan final
Aspek const final Inisialisasi Diinisialisasi pada waktu kompilasi Diinisialisasi pada waktu runtime Imutabilitas Nilai tidak dapat diubah setelah inisialisasi Nilai tidak dapat diubah setelah inisialisasi Tipe Data Harus bertipe data yang diketahui saat kompilasi Tipe data bisa ditentukan saat runtime Penggunaan Memori Dapat dioptimalkan untuk penggunaan memori yang efisien Memori akan dialokasikan untuk setiap instance Contoh const pi = 3.14;
final name = getName();
Scope Dapat digunakan dalam konteks compile-time Dapat digunakan dalam konteks runtime
- Membuat Program Flutter Baru: Pertama, saya membuka terminal dan menggunakan perintah
flutter create pacilbay
untuk membuat aplikasi Flutter baru dengan nama "pacilbay". - Buat file baru bernama menu.dart di direktori mental_health_tracker/lib. Tambahkan kode import 'package:flutter/material.dart'; pada baris pertama file tersebut.
- Di menu.dart, ubah kelas MyHomePage dari StatefulWidget menjadi StatelessWidget dengan menghapus bagian yang tidak diperlukan dan menambahkan constructor baru.
- Di dalam file lib/main.dart, saya mengimplementasikan kelas MyHomePage yang merupakan widget utama aplikasi. Dalam metode build, saya menggunakan widget Column untuk menyusun tombol-tombol secara vertikal. Saya membuat tiga tombol dengan menggunakan widget ElevatedButton, masing-masing dilengkapi dengan ikon dan teks yang sesuai. Untuk mengisi card tersebut, saya deklarasikan tiga variabel bertipe string (npm, name, className) di dalam kelas MyHomePage.
- Selanjutnya, saya buat kelas baru bernama InfoCard di menu.dart untuk menampilkan informasi NPM, nama, dan kelas.
- Selanjutnya, saya mengimplementasikan warna yang berbeda untuk setiap tombol dengan menambahkan properti
final Color color;
pada classItemHomepage
yang sudah dibuat sebelumnya. - Saya menggunakan widget ScaffoldMessenger untuk menampilkan Snackbar ketika tombol ditekan. Dalam setiap fungsi onPressed dari tombol, saya menambahkan kode untuk menampilkan Snackbar yang sesuai
- Setelah semua kelas selesai dimplementasikan, saya menjalankan perintah flutter analyze untuk memastikan tidak ada isu pada kode yang dapat mengganggu performa atau fungsionalitas aplikasi.
const
adalah keyword di Flutter yang digunakan untuk mendefinisikan objek atau widget yang immutable (tidak bisa diubah) dan akan diinisialisasi sekali saja pada saat kompilasi. Dengan const
, kita memastikan bahwa objek tersebut bersifat konstan dan tidak akan berubah sepanjang masa hidup aplikasi.
-
Meningkatkan Performa Aplikasi
- Reuse: Objek
const
hanya dibuat satu kali dalam memori, sehingga dapat digunakan kembali (reused) tanpa perlu dibuat ulang. - Optimasi Rendering: Flutter tidak perlu merender ulang widget yang diberi
const
, sehingga mempercepat proses rendering dan mengurangi kerja CPU.
- Reuse: Objek
-
Efisiensi Memori
- Objek
const
hanya memakan memori sekali saja, karena tidak dibuat ulang setiap kali dipanggil. - Penggunaan memori menjadi lebih hemat, terutama dalam aplikasi dengan banyak widget statis.
- Objek
-
Deteksi Kesalahan di Waktu Kompilasi
- Kesalahan yang berkaitan dengan nilai konstan dapat dideteksi lebih awal, saat proses kompilasi, bukan di runtime.
- Membantu pengembang menemukan bug lebih cepat dan meningkatkan keandalan aplikasi.
-
Meningkatkan Readability dan Maintainability
- Kode yang menggunakan
const
lebih mudah dibaca dan dipahami, karena developer lain tahu bahwa objek tersebut tidak akan berubah. - Membantu menjaga konsistensi dalam kode, sehingga lebih mudah dikelola dan di-maintain.
- Kode yang menggunakan
-
Widget Statis: Ketika widget atau objek tidak berubah selama masa hidup aplikasi.
const Text('Hello, Flutter');
-
Konfigurasi Aplikasi: Untuk nilai-nilai yang tidak berubah, seperti warna, margin, padding, atau konfigurasi lainnya.
const Color primaryColor = Colors.blue;
-
Penggunaan Berulang: Ketika sebuah widget atau objek sering digunakan di berbagai tempat dalam aplikasi.
const EdgeInsets allPadding = EdgeInsets.all(16.0);
-
Widget Dinamis: Jika widget atau objek bergantung pada input User atau data yang berubah.
Text('Welcome, $userName'); // Tidak bisa menggunakan const karena userName bisa berubah
-
Stateful Widget: Untuk widget yang memiliki state atau memerlukan perubahan selama runtime.
setState(() { // Update state });
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Const Example'),
),
body: Center(
child: Text('Hello, const world!'),
),
),
);
}
}
Dalam kode Dart tersebut, penggunaan const memiliki beberapa fungsi:
- Konstruksi class: Konstruktor
MyApp
ditandai sebagai const, yang berarti bahwa setiap instance dariMyApp
tidak akan berubah (immutable) dan dapat diinisialisasi sebagai konstan. Konstruktor ini membantu Flutter memahami bahwa widget ini tidak perlu dirender ulang jika tidak ada perubahan. - Reusable
MaterialApp
: Dengan menggunakan const,MaterialApp
dibuat sebagai objek immutable. Jika tidak ada perubahan pada konfigurasi aplikasi, Flutter tidak perlu membuat ulang widget ini setiap kali aplikasi dijalankan atau dirender ulang. - Immutable
Text
Widget:Text
ini memiliki nilai yang tidak akan berubah selama runtime. Denganconst
, Flutter tidak perlu membuat ulang widget ini, yang meningkatkan efisiensi rendering.
`Column` adalah widget di Flutter yang menyusun *children*-nya secara vertikal (dari atas ke bawah).
**Karakteristik:**
- Menyusun widget secara **vertikal**.
- Bisa menyesuaikan **alignment** dan **main axis** (vertikal) serta **cross axis** (horizontal).
- Fleksibel untuk membuat tata letak dengan elemen-elemen yang harus ditampilkan berurutan dari atas ke bawah.
**Properti Utama:**
- `mainAxisAlignment`: Mengatur bagaimana *children* diatur secara vertikal.
- `crossAxisAlignment`: Mengatur bagaimana *children* disejajarkan secara horizontal.
**Contoh Implementasi:**
```dart
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Item 1'),
Text('Item 2'),
Text('Item 3'),
],
)
```
Penggunaan `Column` dalam kode ini bertujuan untuk menyusun beberapa widget `Text` secara vertikal, dari atas ke bawah.
- `Column` Widget
`Column` digunakan untuk menyusun anak-anaknya (dalam hal ini widget `Text`) secara vertikal.
- `mainAxisAlignment: MainAxisAlignment.center`
Properti `mainAxisAlignment` mengatur posisi anak-anak widget di **sumbu utama** (vertikal dalam `Column`). Dengan `MainAxisAlignment.center`, semua anak-anak `Column` akan ditempatkan di tengah-tengah sumbu vertikal.
- `crossAxisAlignment: CrossAxisAlignment.start`
Properti `crossAxisAlignment` mengatur posisi anak-anak di sepanjang **sumbu sekunder** (horizontal dalam `Column`). Dengan `CrossAxisAlignment.start`, setiap anak dari `Column` akan disejajarkan di sisi **kiri** dari sumbu horizontal.
- `children`
Daftar widget yang merupakan anak-anak dari `Column`. Dalam kode ini, ada tiga widget `Text`:
`Text('Item 1')`
`Text('Item 2')`
`Text('Item 3')`
Ketiga widget ini akan ditampilkan secara vertikal dalam `Column`, dimulai dari sisi kiri (karena `crossAxisAlignment.start`) dan dipusatkan di sumbu vertikal (karena `mainAxisAlignment.center`).
`Row` adalah widget di Flutter yang menyusun *children*-nya secara horizontal (dari kiri ke kanan).
**Karakteristik:**
- Menyusun widget secara **horizontal**.
- Sama seperti `Column`, `Row` memiliki kontrol atas **alignment** dan **main axis** (horizontal) serta **cross axis** (vertikal).
- Digunakan untuk membuat tata letak elemen-elemen yang perlu disusun berurutan dari kiri ke kanan.
**Properti Utama:**
- `mainAxisAlignment`: Mengatur bagaimana *children* diatur secara horizontal.
- `crossAxisAlignment`: Mengatur bagaimana *children* diatur vertikal.
**Contoh Implementasi:**
```dart
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.person),
],
)
```
Kode `Row` ini digunakan untuk menyusun tiga ikon secara horizontal dengan jarak yang merata di antara mereka.
- `Row'
- Widget ini menyusun elemen-elemen anak (`children`) secara horizontal, dari kiri ke kanan.
- `mainAxisAlignment: MainAxisAlignment.spaceAround`. Properti ini mengatur jarak antar elemen anak di **sumbu utama** (horizontal). Dengan `spaceAround`:
- Memberikan jarak yang sama di sekitar setiap elemen.
- Jarak antara elemen dan tepi `Row` sedikit lebih kecil dibandingkan jarak antar elemen.
- `crossAxisAlignment: CrossAxisAlignment.center`
- Properti ini menentukan bagaimana elemen-elemen anak diatur di **sumbu sekunder** (vertikal).
- `center` memastikan semua ikon berada di tengah secara vertikal dalam `Row`.
- `children`
- Berisi tiga ikon: `Icons.star`, `Icons.favorite`, dan `Icons.person`.
- Masing-masing ikon akan ditempatkan secara horizontal dalam `Row` dengan jarak merata.
| **Aspek** | **Column** | **Row** |
|------------------------|-------------------------------------|-------------------------------------------|
| **Orientasi** | Vertikal (dari atas ke bawah) | Horizontal (dari kiri ke kanan) |
| **Main Axis** | Vertikal | Horizontal |
| **Cross Axis** | Horizontal | Vertikal |
| **Penggunaan** | Untuk menyusun elemen vertikal | Untuk menyusun elemen horizontal |
| **Alignment** | `mainAxisAlignment`, `crossAxisAlignment` | `mainAxisAlignment`, `crossAxisAlignment` |
| **Contoh Situasi** | Daftar item, formulir, paragraf | Navigasi horizontal, icons |
```dart
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Left Item'),
Text('Right Item'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.person),
],
),
],
)
```
-
TextFormField
:Nama Produk
: Input teks untuk nama produk dengan validasi untuk memastikan tidak kosong dan tidak lebih dari 100 karakter.Deskripsi Produk
: Input teks untuk deskripsi produk dengan validasi untuk memastikan tidak kosong dan tidak lebih dari 255 karakter.Harga Produk
: Input teks yang memerlukan angka positif untuk harga produk, dengan validasi angka dan memastikan input adalah integer positif.Jumlah Tersedia
: Input teks yang memerlukan angka positif untuk jumlah produk yang tersedia, dengan validasi serupa untuk angka dan integer positif.
-
ElevatedButton
:- Tombol untuk menyimpan data formulir, dengan validasi formulir sebelum menampilkan dialog konfirmasi.
DropdownButton
: Untuk memilih dari daftar pilihan yang sudah ditentukan.Checkbox
: Untuk input nilai boolean (true/false).Radio
: Untuk memilih satu opsi dari beberapa pilihan.Slider
: Untuk input angka dalam bentuk slider.Switch
: Untuk input boolean yang bisa diaktifkan/dinonaktifkan.DatePicker
: Untuk memilih tanggal.TimePicker
: Untuk memilih waktu.
Flutter menyediakan widget ThemeData
yang dapat diatur dalam MaterialApp
untuk memastikan konsistensi tampilan di seluruh aplikasi. Dengan menggunakan ThemeData
, kita bisa mengatur warna, font, bentuk tombol, gaya teks, dan elemen UI lainnya agar konsisten di seluruh aplikasi.
Dalam aplikasi Flutter yang saya buat, saya menggunakan tema utama yang didefinisikan di main.dart
. Tema ini berfungsi sebagai "base" untuk seluruh screens dan widget lainnya, memastikan konsistensi desain dan gaya di seluruh aplikasi.
Di dalam main.dart
, saya mengatur ThemeData
menggunakan colorScheme
dan beberapa pengaturan tambahan:
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.deepOrange,
).copyWith(
secondary: Colors.deepOrange[400],
),
useMaterial3: true, // Mengaktifkan Material Design 3
),
home: MyHomePage(),
);
-
MaterialApp
MaterialApp
adalah widget utama yang membungkus aplikasi Flutter. Parametertheme
membuat kita bisa menentukan tema global yang akan diterapkan ke seluruh aplikasi. -
ThemeData
ThemeData
adalah konfigurasi tema yang berisi berbagai pengaturan seperti skema warna, font, dan gaya lainnya. -
colorScheme
ColorScheme.fromSwatch
: Digunakan untuk membuat skema warna berbasis warna utama yang kita pilih (primarySwatch
). Dalam contoh ini,primarySwatch
diatur keColors.deepOrange
.copyWith
: Digunakan untuk menyesuaikan skema warna lebih lanjut. Dalam kode ini,secondary
diatur keColors.deepOrange[400]
. Warna sekunder biasanya digunakan untuk elemen tambahan seperti tombol aksi sekunder dan ikon.
-
useMaterial3
useMaterial3: true
: Mengaktifkan penggunaan Material Design 3, yang menghadirkan fitur desain baru dan penyesuaian yang lebih baik untuk elemen UI, seperti tombol, card, dan lainnya. -
home
Menentukan layar awal aplikasi, dalam hal ini,
MyHomePage
.
Navigasi dalam aplikasi ini ditangani menggunakan Navigator
dengan metode pushReplacement
dan push
untuk berpindah antar halaman.
Navigator.pushReplacement
digunakan untuk mengganti halaman saat ini dengan halaman baru.Navigator.pushReplacement
memastikan bahwa halaman sebelumnya tidak akan tetap berada dalam stack navigasi.- Keuntungan: User tidak dapat kembali ke halaman sebelumnya dengan tombol "back", sehingga cocok untuk skenario seperti mengalihkan User ke halaman utama atau formulir tertentu setelah tindakan tertentu.
Contoh:
ListTile(
leading: const Icon(Icons.home_outlined),
title: const Text('Halaman Utama'),
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => MyHomePage(),
),
);
},
);
Dalam contoh ini, ketika User mengetuk "Halaman Utama", mereka akan diarahkan ke MyHomePage
, dan halaman sebelumnya akan dihapus dari stack navigasi.
Selain menggunakan pushReplacement
untuk navigasi melalui drawer, saya juga menggunakan Navigator.push
di dalam InkWell
pada halaman menu untuk navigasi ke halaman lain.
Navigator.push
menambahkan halaman baru ke stack navigasi, memungkinkan user untuk kembali ke halaman sebelumnya dengan tombol "back".- Perbedaan dengan
pushReplacement
:push
menambahkan halaman ke stack navigasi.pushReplacement
mengganti halaman saat ini, sehingga halaman sebelumnya dihapus dari stack navigasi.
- Keuntungan: Memungkinkan navigasi dengan kemampuan untuk kembali ke halaman sebelumnya, misalnya, setelah menyelesaikan suatu tugas atau form.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductEntryFormPage(),
),
);
Dalam contoh ini, ketika item menu dengan nama "Tambah Produk" diklik, aplikasi akan menavigasi ke ProductEntryFormPage
, dan user dapat kembali ke halaman sebelumnya dengan tombol "back".
Drawer
adalah komponen navigasi yang menampilkan side menu. User dapat memilih item menu untuk berpindah antar halaman.- Setiap
ListTile
dalamDrawer
memicu navigasi ke halaman yang berbeda. - Contoh item Drawer:
- Halaman Utama: Mengarahkan ke
MyHomePage
. - Tambah Produk: Mengarahkan ke
ProductEntryFormPage
.
- Halaman Utama: Mengarahkan ke
Kode:
Drawer(
child: ListView(
children: [
// Header Drawer
DrawerHeader(...),
// Navigasi ke Halaman Utama
ListTile(
leading: const Icon(Icons.home_outlined),
title: const Text('Halaman Utama'),
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => MyHomePage()),
);
},
),
// Navigasi ke Tambah Produk
ListTile(
leading: const Icon(Icons.shop_2_outlined),
title: const Text('Tambah Produk'),
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => ProductEntryFormPage()),
);
},
),
],
),
);
-
Struktur Data yang Konsisten
- Model menyediakan kerangka atau struktur yang memastikan bahwa data yang diterima atau dikirim memiliki format yang sama.
- Dalam Django, model biasanya digunakan untuk mendefinisikan bagaimana data disimpan dalam database. Saat data ini diubah menjadi JSON (menggunakan serializer), struktur model tetap terjaga.
- Di sisi Flutter, model (dalam bentuk kelas Dart) memastikan data JSON yang diterima dari Django dapat diakses dengan atribut atau metode tertentu. Dengan pendekatan ini, data yang ditransfer antara Django dan Flutter tetap konsisten, mencegah error parsing atau akses atribut yang tidak ada.
-
Validasi Data
- Model di Django (dan serializer) memvalidasi data sebelum menyimpan ke database. Jika tidak ada model, data bisa saja diterima meskipun tidak valid atau tidak sesuai dengan harapan.
- Di Flutter, model memastikan data JSON yang diterima memiliki tipe dan format yang benar.
Contoh Validasi di Django:
class ProductSerializer(serializers.ModelSerializer): class Meta: model = Product fields = ['id', 'name', 'price', 'description'] def validate_price(self, value): if value <= 0: raise serializers.ValidationError("Price must be greater than zero.") return value
Error yang Dapat Terjadi Tanpa Validasi: Jika Flutter menerima JSON tanpa validasi:
{ "id": 1, "name": "Laptop", "price": "not_a_number", "description": "High-performance laptop" }
Maka aplikasi Flutter akan crash ketika mencoba mengubah tipe data
price
menjadidouble
. -
Kemudahan Pengembangan dan Perawatan
- Model berfungsi sebagai sumber kebenaran tunggal (Single Source of Truth) untuk pengelolaan data, baik di Django maupun Flutter.
- Jika ada perubahan pada struktur data (misalnya penambahan atribut baru), model memastikan bahwa perubahan ini diterapkan dengan konsisten pada backend dan frontend.
- Tanpa Model, perubahan harus dilakukan secara manual di beberapa tempat, yang meningkatkan risiko inkonsistensi.
-
Keamanan Data
- Django model dapat dilengkapi dengan kontrol akses dan logika validasi yang mencegah eksploitasi.
- Tanpa model, data mentah yang tidak diverifikasi dapat menyebabkan celah keamanan.
-
Di Django: Tidak menggunakan model Django untuk database (misalnya hanya bekerja dengan data JSON mentah) tidak akan menyebabkan error secara langsung, tetapi akan sangat sulit untuk mengelola data dengan struktur kompleks. Serializer membutuhkan model atau struktur data untuk bekerja dengan baik.
-
Di Flutter: Tanpa model Dart, JSON parsing menjadi tidak efisien dan rawan error. Akses atribut menggunakan cara manual (
json['key']
) dapat menyebabkan error runtime jika atribut tidak ada atau tipe data tidak sesuai.Contoh Masalah Tanpa Model Dart:
var jsonData = {'id': 1, 'name': 'Laptop', 'price': 1500}; // Akses manual var price = jsonData['price']; // Berjalan var description = jsonData['description']; // Error runtime: Key not found
Tanpa model, error eksplisit mungkin tidak langsung ada, tetapi akan ada banyak potensi masalah yang menjadikan program tidak efisien dan rawan bug.
Library `http` dalam Flutter digunakan untuk mengirim HTTP request dari aplikasi Flutter ke layanan backend seperti Django. Library http menyediakan API untuk melakukan request, seperti `GET`, `POST`, `PUT`, `DELETE`, dll sehingga memungkinkan komunikasi antara frontend (Flutter) dan backend (Django).
Fungsi http
dalam integrasi Django dan Flutter:
Pada integrasi flutter dan django, POST digunakan untuk mengirimkan data dari Flutter ke Django. Contohnya, mengirim data formulir menambah user (register).
Kode di Flutter:
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> registerUser(String username, String password) async {
final url = Uri.parse('http://127.0.0.1:8000/api/register/');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'username': username, 'password': password}),
);
if (response.statusCode == 201) {
print('User registered successfully');
} else {
print('Failed to register user: ${response.statusCode}');
}
}
Kode di Django (views.py):
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['POST'])
def register_user(request):
username = request.data.get('username')
password = request.data.get('password')
# Simpan data ke database (contoh sederhana)
if username and password:
return Response({'message': 'User registered'}, status=status.HTTP_201_CREATED)
return Response({'error': 'Invalid data'}, status=status.HTTP_400_BAD_REQUEST)
- Library
http
akan membuat request POST dengan header dan isi request yang sesuai. jsonEncode
digunakan untuk mengonversi data Dart menjadi format JSON yang dapat dipahami Django.- Error handling dilakukan dengan memeriksa
statusCode
.
GET request digunakan untuk mengambil data dari Django, seperti daftar produk atau detail pengguna.
Misalkan aplikasi Flutter perlu mengambil daftar produk dari endpoint Django /api/products/
.
Kode di Flutter:
Future<void> fetchProducts() async {
final url = Uri.parse('http://127.0.0.1:8000/api/products/');
final response = await http.get(url);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
print('Products: $data');
} else {
print('Failed to fetch products: ${response.statusCode}');
}
}
Kode di Django (views.py):
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET'])
def get_products(request):
products = [
{'id': 1, 'name': 'Product 1', 'price': 100},
{'id': 2, 'name': 'Product 2', 'price': 200},
]
return Response(products)
- Fungsi
http.get
mengirimkan permintaan tanpa body, cukup dengan URL. - Data JSON yang diterima dari Django di-decode menggunakan
jsonDecode
di Flutter. - Library
http
meng-handle proses pengambilan data secara asinkron denganFuture
.
PUT request digunakan untuk meng-update data yang sudah ada, seperti mengedit profil pengguna.
Kode di Flutter:
Future<void> updateUser(int userId, String username) async {
final url = Uri.parse('http://127.0.0.1:8000/api/user/$userId/');
final response = await http.put(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'username': username}),
);
if (response.statusCode == 200) {
print('User updated successfully');
} else {
print('Failed to update user: ${response.statusCode}');
}
}
Kode di Django (views.py):
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['PUT'])
def update_user(request, user_id):
username = request.data.get('username')
# Perbarui data di database (contoh sederhana)
if username:
return Response({'message': 'User updated'}, status=status.HTTP_200_OK)
return Response({'error': 'Invalid data'}, status=status.HTTP_400_BAD_REQUEST)
- Library
http
menggunakan method PUT untuk pembaruan data. - Header
Content-Type
memastikan server Django dapat membaca data dalam format JSON.
Permintaan DELETE digunakan untuk menghapus data, seperti menghapus akun pengguna.
Kode di Flutter:
Future<void> deleteUser(int userId) async {
final url = Uri.parse('http://127.0.0.1:8000/api/user/$userId/');
final response = await http.delete(url);
if (response.statusCode == 204) {
print('User deleted successfully');
} else {
print('Failed to delete user: ${response.statusCode}');
}
}
Kode di Django (views.py):
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['DELETE'])
def delete_user(request, user_id):
# Hapus data dari database
return Response({'message': 'User deleted'}, status=status.HTTP_204_NO_CONTENT)
- Fungsi
http.delete
lebih sederhana karena tidak membutuhkan body. - Respons dilakukan untuk memverifikasi keberhasilan penghapusan. (optional)
CookieRequest
adalah sebuah abstraksi yang digunakan untuk mengelola sesi user dalam komunikasi antara aplikasi Flutter dan django. CookieRequest
berfungsi untuk:
-
Mengelola Otorisasi dan Autentikasi
- Django menggunakan cookie untuk melacak status login user setelah proses autentikasi berhasil.
CookieRequest
menangkap cookie ini dan menggunakannya untuk menjaga status login user di sisi klien (Flutter). - Karena cookue sudah ditangkap dengan
CookieRequest
, user tidak perlu login setiap kali melakukan request ke server setelah login.
- Django menggunakan cookie untuk melacak status login user setelah proses autentikasi berhasil.
-
Mengirimkan Header Cookie
CookieRequest
memastikan bahwa setiap request HTTP ke server Django menggunakan header cookie yang sesuai. Hal ini penting untuk mengakses endpoint yang memerlukan otorisasi, seperti mengambil data pribadi atau melakukan perubahan pada data user.
-
Menyimpan Status Sesi
CookieRequest
berperan sebagai sebagai pengelola session yang akan menyimpan cookie selama aplikasi berjalan. Jika aplikasi dimatikan, status session dapat disimpan ke penyimpanan lokal untuk di-reload nanti.
-
Menyediakan Fitur Logout
CookieRequest
juga menangani penghapusan cookie ketika user logout, sehingga session dihapus baik di sisi server maupun klien.
Instance CookieRequest
perlu bersifat global dan dapat diakses oleh semua komponen Flutter supaya user experience tetap konsisten di seluruh aplikasi. Fungsi instance CookieRequest
yang dibagikan ke semua komponen:
-
Membuat Status Session Konsisten
- Semua bagian aplikasi yang memerlukan data dari server membutuhkan status session yang sama. Pembagian instance
CookieRequest
ke seluruh komponen, semua HTTP request akan dilakukan menggunakan cookie yang sama.
- Semua bagian aplikasi yang memerlukan data dari server membutuhkan status session yang sama. Pembagian instance
-
Mencegah Redundansi
- Jika setiap komponen membuat instance
CookieRequest
sendiri, akan terjadi konflik dalam penyimpanan cookie yang akan mengurangi efisiensi, dan meningkatkan kompleksitas debugging.
- Jika setiap komponen membuat instance
-
Peningkatan Keamanan
- Dengan membagikan instance
CookieRequest
ke semua komponen, pengelolaan cookie menjadi lebih terpusat. Pengelolaan cookie yang terpusat akan meminimalkan risiko (misal pengiriman header cookie yang salah atau penyimpanan cookie yang tidak terenkripsi).
- Dengan membagikan instance
-
Kemudahan Integrasi
- Banyak fitur aplikasi (login otomatis, sinkronisasi data, atau pengelolaan cache) yang bergantung pada cookie yang sama. Instance global membuat semua fitur ini berfungsi dengan baik dan mengurangi kemungkinan konflik.
-
Input Data di Aplikasi Flutter
- User mengisi form di aplikasi Flutter dengan widget
TextFormField
yang sudah dibuat dengan field sesuai model yang sudah dibuat di django:- Nama Produk (
_productName
) - Deskripsi Produk (
_productDescription
) - Harga Produk (
_price
) - Jumlah Tersedia (
_availableQty
)
- Nama Produk (
- Widget form menggunakan validator untuk memeriksa validitas input (angka positif untuk harga, panjang maksimal string, dsb.).
- User mengisi form di aplikasi Flutter dengan widget
-
Klik Tombol "Save"
- Setelah user mengisi semua field, user dapat menekan tombol "Save" jika semua validator terpenuhi.
- Tombol ini memicu fungsi asynchronous di Flutter untuk mengirimkan data ke server Django.
-
Persiapan Data untuk Pengiriman
- Fungsi
request.postJson
pada Flutter digunakan untuk membuat HTTP POST request. - Data input dari user (
_productName
,_productDescription
,_price
, dan_availableQty
) diterjemahkan dalam format JSON menggunakan fungsijsonEncode
.
- Fungsi
-
Pengiriman HTTP Request ke Server Django
- Endpoint tujuan adalah
http://127.0.0.1:8000/create-flutter/
. - Header request secara otomatis mengandung
Content-Type: application/json
untuk memberi tahu Django bahwa data dikirim dalam format JSON. - Payload JSON berisi:
{ "product_name": "Example Product", "price": "100", "product_description": "Example Description", "available_qty": "10" }
- Endpoint tujuan adalah
-
Penerimaan dan Pemrosesan Data di Django
- Fungsi
create_product_flutter
pada Django menerima request POST. - Dekorator
@csrf_exempt
memastikan bahwa request dari Flutter tidak memerlukan token CSRF. - Request body yang berupa JSON di-parse menggunakan
json.loads(request.body)
.
- Fungsi
-
Validasi dan Penyimpanan Data di Django
- Django membaca data yang diterima dan membuat objek baru
ProductEntry
menggunakan model Django. - Field yang diisi adalah:
- user: Otentikasi pengguna diambil dari
request.user
. - product_name: Data dari
data["product_name"]
. - price: Data dari
data["price"]
di-casting menjadi integer. - product_description: Data dari
data["product_description"]
. - available_qty: Data dari
data["available_qty"]
di-casting menjadi integer.
- user: Otentikasi pengguna diambil dari
- Objek kemudian disimpan ke database dengan
new_product.save()
.
- Django membaca data yang diterima dan membuat objek baru
-
Respon Django ke Flutter
- Jika data berhasil disimpan, Django mengembalikan respons JSON dengan status
200 OK
:{ "status": "success" }
- Jika metode selain POST digunakan, Django mengembalikan respons dengan status
401 Unauthorized
:{ "status": "error" }
- Jika data berhasil disimpan, Django mengembalikan respons JSON dengan status
-
Pengolahan Respons di Flutter
- Setelah respons diterima, Flutter memproses JSON menggunakan key
response['status']
:- Jika status adalah
success
, aplikasi:- Menampilkan SnackBar dengan pesan "Produk baru berhasil disimpan!".
- Mengarahkan user kembali ke halaman
MyHomePage
denganNavigator.pushReplacement
.
- Jika status adalah
error
, aplikasi:- Menampilkan SnackBar dengan pesan "Terdapat kesalahan, silakan coba lagi.".
- Jika status adalah
- Setelah respons diterima, Flutter memproses JSON menggunakan key
-
User Melihat Data Tersimpan
- Setelah pengiriman sukses, data produk baru sudah tersimpan di database Django.
- Data ini dapat diambil oleh Flutter melalui endpoint GET untuk ditampilkan dalam aplikasi.
- Flutter: User mengisi form → Klik Save → JSON dikirim via HTTP POST →
- Django: Menerima JSON → Parsing → Simpan data ke database → Berikan respons JSON →
- Flutter: Terima respons → Tampilkan notifikasi dan navigasi ulang.
-
Input Data di Flutter:
- User memasukkan username, password, dan konfirmasi password melalui form di Flutter (
RegisterPage
).
- User memasukkan username, password, dan konfirmasi password melalui form di Flutter (
-
Mengirim Data ke Django:
- Flutter mengirimkan data ke endpoint Django
/auth/register/
menggunakan metode POST. - Data dikirim dalam format JSON, berisi
username
,password1
, danpassword2
.
- Flutter mengirimkan data ke endpoint Django
-
Django Memproses Permintaan:
- Django menerima data melalui fungsi
register(request)
. - Data JSON di-parse untuk memvalidasi:
- Apakah password cocok.
- Apakah username sudah ada di database.
- Jika valid, Django membuat akun menggunakan
User.objects.create_user
.
- Django menerima data melalui fungsi
-
Respons dari Django:
- Jika pendaftaran berhasil, Django mengembalikan respons JSON:
{ "username": "username_pengguna", "status": "success", "message": "User created successfully!" }
- Jika gagal, Django mengirimkan pesan kesalahan.
- Jika pendaftaran berhasil, Django mengembalikan respons JSON:
-
Feedback ke Flutter:
- Flutter menampilkan pesan sukses atau gagal kepada pengguna.
-
Input Data di Flutter:
- User memasukkan
username
danpassword
di form login pada Flutter.
- User memasukkan
-
Mengirim Data ke Django:
- Flutter mengirimkan data ke endpoint
/auth/login/
menggunakan metode POST. - Data dikirim dalam format form-urlencoded (bukan JSON) karena Django membaca
request.POST
.
- Flutter mengirimkan data ke endpoint
-
Django Memproses Permintaan:
- Django menerima data login melalui fungsi
login(request)
:- Django mencoba mengotentikasi pengguna dengan
authenticate(username=username, password=password)
. - Jika autentikasi berhasil:
- Django memanggil
auth_login(request, user)
untuk membuat sesi login. - Django mengirim respons JSON:
{ "username": "username_pengguna", "status": true, "message": "Login sukses!" }
- Django memanggil
- Jika gagal:
- Django mengirim respons kesalahan:
{ "status": false, "message": "Login gagal, periksa kembali email atau kata sandi." }
- Django mengirim respons kesalahan:
- Django mencoba mengotentikasi pengguna dengan
- Django menerima data login melalui fungsi
-
Feedback di Flutter:
- Jika berhasil:
- Flutter menyimpan status login dan mengarahkan pengguna ke halaman
MyHomePage
(menu utama). - Pesan sukses ditampilkan menggunakan
SnackBar
.
- Flutter menyimpan status login dan mengarahkan pengguna ke halaman
- Jika gagal:
- Pesan kesalahan ditampilkan dalam
AlertDialog
.
- Pesan kesalahan ditampilkan dalam
- Jika berhasil:
-
Trigger Logout di Flutter:
- User menekan tombol logout di Flutter.
-
Mengirim Permintaan ke Django:
- Flutter mengirim permintaan GET/POST ke endpoint
/auth/logout/
.
- Flutter mengirim permintaan GET/POST ke endpoint
-
Django Memproses Permintaan:
- Django memanggil
auth_logout(request)
untuk menghapus sesi pengguna. - Django mengirimkan respons JSON:
{ "username": "username_pengguna", "status": true, "message": "Logout berhasil!" }
- Django memanggil
-
Feedback di Flutter:
- Flutter menampilkan pesan sukses dan mengarahkan pengguna kembali ke halaman login.
-
Saya membuat django-app bernama
authentication
untuk memisahkan fungsi autentikasi ke dalam modul terpisah supaya lebih terstruktur dan mudah dikelola dengan menjalankan perintah:python manage.py startapp authentication
-
Saya menambahkan
authentication
keINSTALLED_APPS
di proyek Django agar Django mengenali aplikasi ini dan kode di dalamnya dapat digunakan -
Saya menginstal
django-cors-headers
yang memungkinkan Django menangani permintaan dari domain berbeda (CORS). Dengan demikian, flutter (yang berjalan di domain berbeda) berkomunikasi dengan backend Django. Saya juga menambahkan jugadjango-cors-headers
ke filerequirements.txt
untuk dokumentasi dependensi. -
Saya menambahkan konfigurasi CORS ke
settings.py
agar Django mengizinkan akses lintas domain dan menangani cookie secara aman. Hal ini memastikan autentikasi antara Flutter dan Django dapat bekerja meskipun berasal dari domain berbeda dengan memambahkan kesettings.py
:CORS_ALLOW_ALL_ORIGINS = True CORS_ALLOW_CREDENTIALS = True CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SAMESITE = 'None' SESSION_COOKIE_SAMESITE = 'None'
-
Saya menambahkan
corsheaders
keINSTALLED_APPS
danMIDDLEWARE
untuk mengaktifkan dan mengatur middleware CORS di Django. Hal ini memastikan setiap request ke Django melalui validasi CORS sebelum diproses.- Tambahkan ke
INSTALLED_APPS
:INSTALLED_APPS = [ ... 'corsheaders', ]
- Tambahkan middleware:
MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ]
- Tambahkan ke
-
Saya menambahkan
10.0.2.2
keALLOWED_HOSTS
untuk emulator Android sehingga alamat localhost emulator Android terdaftar ke host yang diizinkan Django. Dengan demikian, flutter (yang berjalan di emulator) dapat terhubung ke server Django di komputer lokal. -
Saya membuat metode
login
diauthentication/views.py
untuk memproses permintaan login dari Flutter. Fungsi ini akan memvalidasi kredensial pengguna dan memberikan respons sesuai status autentikasi. -
Saya membuat
urls.py
di folderauthentication
untuk menentukan endpoint untuk fungsilogin
. URL ini yang akan digunakan oleh Flutter untuk mengakses login API. -
Saya menambahkan endpoint
auth/
keurls.py
utama untuk menghubungkan URL aplikasiauthentication
ke proyek utama. -
Saya memastikan Django dapat menerima request dari Flutter menggunakan URL emulator (
http://10.0.2.2
) untuk menghubungkan Flutter ke Django. -
Selanjutnya, saya menginstall package
provider
untuk state management yang memungkinkan objek sepertiCookieRequest
dibagikan ke seluruh aplikasi.
Packagepbp_django_auth
akan menangani autentikasi dengan Django (termasuk pengiriman request HTTP (GET/POST)) dan pengelolaan cookie. -
Saya memodifikasi root eidget dengan mengubah
home: MyHomePage(),
menjadi:
home: const LoginPage(),
Root widget diubah untuk bisa menggunakan state management dengan menambahkan Provider
sebagai wrapper. CookieRequest
digunakan untuk mengelola autentikasi user, seperti login dan logout, dengan Django backend.
-
Saya membuat halaman login untuk menerima input username dan password dari pengguna. Form ini memanfaatkan
CookieRequest
untuk mengirimkan data ke endpoint/auth/login/
Django backend. -
Saya melakukan penyesuaian pada django backend dengan modifikasi file
views.py
, menambahkan endpoint/register/
untuk meng-handle pendaftaran user baru yang mencakup:- Memeriksa kecocokan password.
- Memastikan username belum digunakan.
- Membuat akun baru jika validasi berhasil.
-
Saya membuat halaman register di
register.dart
untuk user membuat akun baru. Mirip dengan halaman login, tetapi form ini mencakup field tambahan untuk konfirmasi password.
-
Saya menambahkan dependensi
http
pada proyek Flutter untuk menambahkan packagehttp
, yang dibutuhkan untuk melakukan HTTP request dari aplikasi Flutter ke backend Django. -
Saya memberikan izin akses internet pada proyek Flutter dengan mengedit file
android/app/src/main/AndroidManifest.xml
untuk menambahkan izin akses internet dengan menyisipkan kode<uses-permission android:name="android.permission.INTERNET" />
. -
Saya membuat halaman baru untuk fetch data di Flutter, membuat file baru bernama
list_moodentry.dart
di direktorilib/screens
. File ini akan digunakan untuk mengambil data dari Django dan menampilkannya di aplikasi Flutter. -
Saya mengimpor library yang dibutuhkan pada file
list_moodentry.dart
dan modul proyek sepertimodels/mood_entry.dart
untuk melakukan pengelolaan data dan rendering UI. -
Saya membuat fungsi
fetchMood
untuk mengambil data dari Django di dalam filelist_moodentry.dart
, yang menggunakan packagehttp
untuk mengirimkan GET request ke endpoint Django. Fungsi ini men-decode respons JSON dan mengonversinya menjadi daftar objekMoodEntry
. -
Saya membuat UI untuk menampilkan daftar mood dan menambahkan kode di dalam widget
FutureBuilder
untuk menangani data yang diambil kemudian menampilkan daftar mood berdasarkan data yang diterima. -
Saya menambahkan menu navigasi ke halaman daftar mood dengan mengedit file
widgets/left_drawer.dart
, menambahkanListTile
baru untuk mengarahkan user ke halamanMoodEntryPage
dengan menggunakanNavigator.push
. -
Saya memperbarui fungsi tombol navigasi utama
widgets/mood_card.dart
, menambahkan logika pada tombol "Lihat Mood" agar mengarahkan user ke halamanMoodEntryPage
. -
Saya menjalankan aplikasi untuk menguji fungsi integrasi, memastikan data
MoodEntry
yang ditambahkan melalui situs web Django berhasil diambil dan ditampilkan dengan benar di aplikasi Flutter.
-
Saya membuat endpoint Django untuk autentikasi login, register, dan logout. Fungsi-fungsi seperti
login
,register
, danlogout
di Django menerima request dari Flutter, memprosesnya, dan mengembalikan respons dalam format JSON. -
Saya menambahkan URL routing pada
urls.py
dan memastikan Flutter dapat mengakses fungsi view di Django. -
Saya menambahkan logika pengiriman data login di Flutter menggunakan
CookieRequest
. Flutter mengirimkan username dan password ke endpoint login Django menggunakan method POST. Django memverifikasi data dan mengembalikan status autentikasi. -
Saya menangani respons autentikasi di Flutter. Jika login berhasil, Flutter menampilkan pesan sukses dan berpindah ke halaman menu. Jika gagal, pesan error muncul di dialog atau snackbar.
-
Saya memastikan session atau token disimpan di Flutter untuk autentikasi berkelanjutan.
CookieRequest
akan menyimpan cookies atau session sehingga user tidak perlu login ulang setiap kali membuka aplikasi. -
Kemudian, saya membuat view Django untuk menerima data dari Flutter. Fungsi
create_mood_flutter
memproses data JSON yang dikirim Flutter, membuat instance model, dan menyimpannya ke database. -
Saya menambahkan endpoint untuk view di
urls.py
:path('create-flutter/', create_mood_flutter, name='create_mood_flutter')
untuk menghubungkan fungsi Django dengan Flutter. -
Saya menghubungkan halaman form di Flutter dengan
CookieRequest
.context.watch<CookieRequest>()
memungkinkan Flutter mengakses cookies atau session untuk otentikasi request. -
Saya menyesuaikan logika pengiriman data di tombol submit Flutter menggunakan method POST untuk mengirim data form (mood, intensitas, dll.) ke endpoint Django. Data dikemas dalam JSON.
-
Saya menangani respons Django di Flutter. Jika Django mengembalikan status sukses, saya menampilkan snackbar di Flutter dan mengarahkan user kembali ke halaman utama. Jika gagal, pesan error muncul.
Langkah pada Django
-
Saya membuat metode view untuk logout. Pada
authentication/views.py
, saya menambahkan fungsilogout
. Fungsi ini memanggilauth_logout
untuk menghapus sesi pengguna yang aktif. Jika berhasil, program mengembalikan respons JSON dengan pesan "Logout berhasil," atau pesan error jika gagal. -
Saya menambahkan path baru untuk logout. Di
authentication/urls.py
, saya menambahkan pathlogout/
yang menghubungkan URL ini dengan fungsi view logout. Hal ini memungkinkan Django menerima request logout dari Flutter.
Langkah pada Flutter
3. Saya membuka file yang menangani logout di Flutter. Di lib/widgets/mood_card.dart
, saya mempersiapkan integrasi dengan fitur logout di backend Django.
-
Saya mengubah perintah
onTap
menjadionTap: () async {...}
. Hal ini memastikan bahwa fungsi logout dijalankan secara asinkron. Saya menggunakanasync
untuk menangani proses komunikasi dengan server. -
Saya menambahkan logika untuk request logout. Di dalam
async {...}
, saya menambahkan request logout ke endpoint Django menggunakanrequest.logout
. Setelah server merespons, saya menangani pesan keberhasilan atau kegagalan logout.- Jika logout berhasil, saya menunjukkan Snackbar dengan pesan "Sampai jumpa," dan menavigasi ulang pengguna ke halaman login.
- Jika gagal, saya tetap menunjukkan Snackbar dengan pesan error.