Episode ini mengorganisasi pergerakan antar layar: perbedaan Navigator 1.0 dan Navigator 2.0, named routes dan nested routes, deep linking, modular app architecture dengan feature modules, serta code organization dan separation of concerns.

Saat aplikasi memiliki puluhan layar, Navigator.push satu per satu menjadi tidak terkelola. Episode 11 membangun sistem navigasi yang jelas dan arsitektur kode yang mendukung pertumbuhan: perbedaan Navigator 1.0 dan 2.0, named routes dan nested routes, deep linking, modular architecture dengan feature modules, serta separation of concerns.
Navigator 1.0 bersifat imperatif: kalian memanggil push dan pop langsung. Navigasi 2.0 bersifat deklaratif: URL atau state menentukan tampilan, dan framework menyesuaikan stack secara otomatis.
Navigator 2.0 lebih kuat — mendukung deep linking dan kontrol penuh atas stack — tetapi boilerplate-nya berat. Solusi pragmatis yang banyak dipakai komunitas adalah package go_router yang membungkus Navigator 2.0 dengan API sederhana:
flutter pub add go_routerUntuk aplikasi dengan navigasi sederhana, Navigator 1.0 dengan named routes masih valid. Untuk aplikasi yang butuh deep linking, state persistence, atau banyak nested flow, go_router adalah pilihan yang paling seimbang.
Daftarkan rute sekali di MaterialApp, lalu navigasi pakai nama:
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => const HomeScreen(),
'/detail': (context) => const DetailScreen(),
'/profil': (context) => const ProfilScreen(),
},
)Navigasi memakai nama rute:
Navigator.pushNamed(context, '/detail');Navigator.pushNamed(context, '/detail') memindahkan pengguna ke rute yang terdaftar. Nama rute memisahkan keputusan "ke mana" dari detail widget, sehingga layar bisa diatur ulang tanpa menyentuh setiap call site.
Dengan go_router, rute didefinisikan sebagai path yang juga bisa dibuka dari luar aplikasi:
final router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/produk/:id',
builder: (context, state) {
return ProdukScreen(id: state.pathParameters['id']!);
},
),
],
);state.pathParameters['id'] mengambil parameter dari URL /produk/123. Karena path-nya URL nyata, rute yang sama bisa di-buka lewat deep link dari luar aplikasi — pola penting untuk notification dan share link.
go_router mendukung routes bersarang melalui ShellRoute, yang memungkinkan navigasi di dalam tab atau drawer tanpa mengunci seluruh halaman. Ini cara standar membangun aplikasi dengan bottom navigation yang tiap tab-nya punya stack sendiri.
Alih-alih folder per tipe (screens/, widgets/, models/), pecah per fitur. Setiap fitur berisi lapisan yang dibutuhkannya sendiri:
features/auth/ — model, repository, controller, dan layar login.features/home/ — layar beranda dan widget terkait.features/cart/ — state keranjang dan tampilannya.lib/
features/
auth/
auth_screen.dart
auth_controller.dart
auth_repository.dart
home/
home_screen.dart
core/
theme/
widgets/
network/
main.dartStruktur di atas memisahkan features (kode bisnis) dari core (kode bersama). Perubahan pada satu fitur tidak menyentuh fitur lain, dan on-boarding developer baru lebih cepat karena konteks berdekatan.
Bahkan dalam satu fitur, pisahkan tanggung jawab:
class AuthRepository {
final http.Client client;
const AuthRepository(this.client);
Future<AuthSession> login(String email, String password) async {
final response = await client.post(
Uri.parse('https://api.example.com/login'),
body: {'email': email, 'password': password},
);
return AuthSession.fromJson(response.body);
}
}AuthRepository menyembunyikan detail HTTP dari UI. Layar cukup memanggil repository.login(...), tanpa tahu bagaimana request dibentuk — ini separation of concerns dalam praktik.
Jangan taruh semua fungsi di satu file utils.dart atau satu controller raksasa. Setiap class harus punya satu alasan untuk berubah. Disiplin ini terasa berlebihan di project kecil, tetapi menjadi penentu di project berskala production.
Inti yang harus dibawa pulang:
go_router membungkus Navigator 2.0 dengan API sederhana dan dukungan deep linking.state.pathParameters membaca parameter dari path URL.Di episode 12 selanjutnya kita membahas platform integration dan plugins — menggunakan platform channels untuk fungsionalitas native, mengintegrasikan device API seperti camera, location, dan sensors, pengembangan custom plugin, serta pengelolaan kompatibilitas plugin dan kode spesifik platform. Aplikasi kalian mulai menyentuh kemampuan perangkat keras.