Navigator.push
Pindah halaman dengan MaterialPageRoute dan tumpukan navigasi.
Analogi: Tumpukan Piring
Bayangkan tumpukan piring di dapur. Menaruh piring baru di atas tumpukan itu push: piring lama tetap ada di bawah, tertutup sementara. Mengambil piring teratas itu pop: piring di bawahnya muncul lagi persis seperti semula, lengkap dengan "isi"-nya (state yang tidak hilang).
Navigasi Flutter bekerja persis seperti itu. Setiap halaman adalah piring, dan Navigator mengelola tumpukannya (disebut route stack). Tombol back di Android pada dasarnya memanggil pop: mengambil halaman teratas sehingga halaman sebelumnya muncul kembali.
Contoh 1: Push Dasar dan Mengirim Data
Pola paling umum: dari daftar, ketuk item untuk membuka halaman detail, sambil mengirim objek data lewat constructor.
// Di halaman daftar
ListTile(
title: Text(produk.nama),
trailing: const Icon(Icons.chevron_right),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HalamanDetail(produk: produk),
),
);
},
);
// Halaman tujuan menerima data lewat constructor biasa
class HalamanDetail extends StatelessWidget {
final Produk produk;
const HalamanDetail({super.key, required this.produk});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(produk.nama)),
body: Padding(
padding: const EdgeInsets.all(16),
child: Text('Harga: ${formatRupiah(produk.harga)}'),
),
);
}
}MaterialPageRoute memberi animasi transisi bawaan sesuai platform (geser dari kanan di Android, dari bawah di iOS untuk fullscreen dialog). Parameter builder dipanggil Flutter untuk membangun halaman tujuan.
Contoh 2: Menunggu Hasil dengan Pop Berdata
Navigasi tidak cuma satu arah. Halaman yang dibuka bisa mengembalikan data saat ditutup, seperti formulir pemilih warna atau tanggal.
// Membuka halaman pilih warna, lalu menunggu hasilnya
Future<void> _pilihWarna() async {
final dipilih = await Navigator.push<String>(
context,
MaterialPageRoute(builder: (context) => const HalamanPilihWarna()),
);
// Widget ini mungkin sudah tidak ada saat future selesai!
if (!mounted) return;
if (dipilih != null) {
setState(() => warna = dipilih);
}
}
// Di halaman pilih warna: kembalikan data lewat pop
ListTile(
title: const Text('Merah'),
onTap: () => Navigator.pop(context, 'merah'),
)Dua detail penting di sini: Navigator.push<String> menentukan tipe data yang dikembalikan, dan pengecekan mounted setelah await memastikan widget pemanggil masih hidup sebelum setState dipanggil. Tanpa cek ini, kamu bisa kena error "setState called after dispose".
Edge Cases
- Context yang tidak valid: jangan simpan
contextdi field atau variabel global lalu dipakai nanti. Selalu pakaicontextyang datang dari parameterbuildatau dari callback yang sedang berjalan. - Back bawaan vs data belum tersimpan: tombol back otomatis mem-pop tanpa bertanya. Kalau halaman berisi formulir yang belum disimpan, bungkus dengan
PopScope(Flutter 3.10+) untuk menampilkan dialog konfirmasi "Yakin ingin keluar?". - Push berkali-kali: menekan tombol "detail" cepat berkali-kali bisa mendorong halaman yang sama berkali-kali ke stack. Nonaktifkan tombol saat proses push, atau cek sebelum push.
Kapan JANGAN Memakai Push Mentah
- Alur login dan onboarding: setelah login berhasil, pakai
pushReplacementataupushAndRemoveUntilagar pengguna tidak bisa menekan back dan kembali ke halaman login. - Deep link dan URL web:
pushmentah tidak punya nama route, jadi tidak bisa diakses lewat URL. Pakai named routes (Navigator.pushNamed) ataugo_router(Navigator 2.0) kalau butuh deep linking. - Stack yang dalam dan kompleks (tab + dialog + halaman bersarang): pertimbangkan
go_routeragar seluruh struktur navigasi terdefinisi di satu tempat.
Praktik Terbaik
- Untuk transisi custom (fade, scale, shared element), pakai
PageRouteBuilderalih-alih mengakaliMaterialPageRoute. - Saat jumlah halaman melewati 5, pindahkan ke named routes agar daftar route terpusat dan mudah di-refactor.
- Jangan pernah memanggil
Navigator.pushdi dalambuildsecara langsung: dorong navigasi dari event (ketukan tombol) atau dariaddPostFrameCallback, bukan dari proses membangun UI.
Catatan teknis:
Navigatoryang kamu pakai sebenarnya adalah Navigator 1.0 (imperative API). Ia tetap didukung penuh dan cocok untuk sebagian besar aplikasi; Navigator 2.0 (declarative, viago_router) baru dibutuhkan saat kamu berurusan dengan URL, deep link, atau web.
Tantangan
Dua halaman
Buat HalamanA dengan tombol 'Ke Halaman B'. HalamanB menampilkan teks 'Ini Halaman B' dan AppBar otomatis punya tombol back.