Exception Handling
Menangani error dengan elegan: try-catch, on, finally, dan throw custom exception.
Program yang tidak gampang mati
Error itu pasti terjadi: file tidak ada, internet putus, user memasukkan teks di kolom angka. Exception handling memastikan program menangani error dengan anggun, bukan crash dan menutup paksa.
void main() {
try {
int angka = int.parse('bukan angka'); // melempar FormatException
print(angka);
} catch (e) {
print('Terjadi error: $e');
}
print('Program tetap jalan');
}Blok try berisi kode berisiko, catch menangkap errornya. Program lanjut ke baris setelah catch, tidak mati.
on: tangkap tipe spesifik
Kadang error berbeda butuh penanganan berbeda:
void main() {
try {
int angka = int.parse('abc');
var list = [1, 2, 3];
print(list[10]);
} on FormatException catch (e) {
print('Format salah: $e');
} on RangeError catch (e) {
print('Index keluar batas: $e');
} catch (e) {
print('Error lain: $e');
}
}on FormatException hanya menangkap error tipe itu. Urutan penting: yang spesifik dulu, catch umum paling akhir sebagai jaring pengaman.
finally: selalu dijalankan
void main() {
try {
print('Buka koneksi...');
throw Exception('Koneksi putus!');
} catch (e) {
print('Tangkap: $e');
} finally {
print('Tutup koneksi.'); // selalu jalan, error atau tidak
}
}Blok finally cocok untuk bersih-bersih: tutup file, tutup koneksi database, sembunyikan loading spinner.
throw: melempar error sendiri
Fungsi juga boleh "protes" kalau inputnya tidak masuk akal:
double bagi(double a, double b) {
if (b == 0) {
throw Exception('Pembagi tidak boleh nol!');
}
return a / b;
}
void main() {
try {
print(bagi(10, 0));
} catch (e) {
print('Gagal: $e');
}
}Custom exception: error yang bermakna
Untuk aplikasi serius, bikin class exception sendiri supaya pesannya jelas:
class SaldoKurang implements Exception {
final String pesan;
SaldoKurang(this.pesan);
@override
String toString() => 'SaldoKurang: $pesan';
}
void tarik(double saldo, double jumlah) {
if (jumlah > saldo) {
throw SaldoKurang('Butuh Rp$jumlah tapi saldo cuma Rp$saldo');
}
print('Tarik Rp$jumlah berhasil');
}
void main() {
try {
tarik(50000, 100000);
} on SaldoKurang catch (e) {
print(e); // SaldoKurang: Butuh Rp100000.0 tapi saldo cuma Rp50000.0
}
}Catatan teknis: Jangan pakai try-catch untuk logika normal program. Exception itu untuk kondisi luar biasa, bukan alur biasa. Contoh salah: pakai try-catch untuk cek apakah key ada di map (pakai
containsKeysaja). Exception itu mahal dan membuat alur kode sulit diikuti. Aturannya: kalau bisa dicek denganif, pakaiif.
Exception dan async
Error di dalam Future ditangkap dengan try-catch di sekitar await:
Future<String> ambilData() async {
await Future.delayed(Duration(seconds: 1));
throw Exception('Server error 500');
}
void main() async {
try {
await ambilData();
} catch (e) {
print('Gagal ambil data: $e');
}
}Tanpa try-catch, error async jadi unhandled dan bisa crash aplikasi. Di Flutter, selalu bungkus pemanggilan API dengan try-catch dan tampilkan pesan ramah ke user.