Flutter Navigation 2.0 dan GoRouter di 2026: Deep Linking dan Pertanyaan Interview
Panduan lengkap navigasi Flutter dengan GoRouter 17.5: routing deklaratif, deep linking, ShellRoute, route guards, dan pertanyaan interview dengan contoh kode.

Navigasi Flutter telah berkembang secara signifikan sejak diperkenalkannya Navigation 2.0. GoRouter 17.5, paket resmi dari tim Flutter, kini menangani kompleksitas Router API sambil menyediakan routing deklaratif, deep linking otomatis, dan nested navigation secara out of the box.
Tim Flutter menganggap GoRouter sudah feature-complete per 2026. Paket ini mendukung path parameters, query parameters, redirects, ShellRoute untuk UI persisten, dan StatefulShellRoute untuk mempertahankan state tab. Navigator 2.0 mentah jarang diimplementasikan secara manual di production.
Memahami Arsitektur Navigator 2.0
Navigator 2.0 memperkenalkan pendekatan deklaratif dan berbasis URL untuk navigasi Flutter. Alih-alih panggilan imperatif push dan pop, state aplikasi menentukan apa yang muncul di navigation stack. Arsitektur ini bergantung pada tiga kelas inti:
- Router: Widget tingkat atas yang mengkoordinasikan navigasi
- RouteInformationParser: Menerjemahkan URL menjadi state aplikasi
- RouterDelegate: Membangun widget tree berdasarkan state tersebut
Ketika deep link tiba dari OS atau URL berubah di browser web, framework memperbarui state, dan UI bereaksi. Masalahnya: menulis RouterDelegate dan RouteInformationParser kustom secara manual membutuhkan boilerplate yang signifikan.
// Raw Navigator 2.0 approach - verbose and rarely used directly
class AppRouterDelegate extends RouterDelegate<AppRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<AppRoutePath> {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
AppRoutePath? _currentPath;
AppRoutePath? get currentConfiguration => _currentPath;
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: [
const MaterialPage(child: HomeScreen()),
if (_currentPath?.isProductPage == true)
MaterialPage(child: ProductScreen(id: _currentPath!.productId!)),
],
onDidRemovePage: (page) {
// Handle page removal
},
);
}
Future<void> setNewRoutePath(AppRoutePath path) async {
_currentPath = path;
notifyListeners();
}
}Verbositas inilah mengapa GoRouter ada. GoRouter membungkus Navigator 2.0 dan menangani boilerplate tersebut.
Menyiapkan GoRouter 17.5
GoRouter 17.5 memperkenalkan dukungan route metadata dan regular expression constraints untuk path parameters. Persyaratan SDK minimum adalah Flutter 3.32 dan Dart 3.8.
import 'package:go_router/go_router.dart';
final goRouter = GoRouter(
initialLocation: '/',
debugLogDiagnostics: true, // Useful during development
routes: [
GoRoute(
path: '/',
name: 'home',
builder: (context, state) => const HomeScreen(),
routes: [
GoRoute(
path: 'products/:id', // Path parameter
name: 'product',
builder: (context, state) {
final productId = state.pathParameters['id']!;
return ProductScreen(productId: productId);
},
),
GoRoute(
path: 'search',
name: 'search',
builder: (context, state) {
// Query parameters: /search?q=flutter&category=books
final query = state.uri.queryParameters['q'] ?? '';
final category = state.uri.queryParameters['category'];
return SearchScreen(query: query, category: category);
},
),
],
),
],
);Router ini terintegrasi dengan MaterialApp.router:
import 'package:flutter/material.dart';
import 'router_config.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: goRouter,
title: 'GoRouter Demo',
);
}
}Konfigurasi Deep Linking untuk Android dan iOS
Deep linking memungkinkan URL eksternal membuka layar tertentu di aplikasi. GoRouter menangani routing secara otomatis setelah konfigurasi platform selesai.
Android App Links
Android membutuhkan intent-filter di AndroidManifest.xml dan file Digital Asset Links yang di-host di domain:
<!-- android/app/src/main/AndroidManifest.xml -->
<activity android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="example.com"
android:pathPrefix="/products" />
</intent-filter>
</activity>File assetlinks.json harus disajikan di https://example.com/.well-known/assetlinks.json.
iOS Universal Links
Untuk iOS, kemampuan Associated Domains harus diaktifkan di Xcode, dan file apple-app-site-association harus di-host:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.example.app",
"paths": ["/products/*", "/search"]
}
]
}
}GoRouter 17.5 memperbaiki bug kritis di mana deep link cold-start Android dengan path kosong kehilangan scheme dan authority. Ini berarti deep link sekarang berfungsi dengan andal bahkan ketika aplikasi tidak berjalan.
Uji deep links Android dengan adb shell am start -a android.intent.action.VIEW -d "https://example.com/products/123". Untuk iOS, gunakan xcrun simctl openurl booted "https://example.com/products/123".
ShellRoute untuk UI Navigasi Persisten
ShellRoute membungkus child routes dengan elemen UI persisten seperti BottomNavigationBar atau Drawer. Shell tetap terlihat saat bernavigasi antar children-nya.
final goRouter = GoRouter(
initialLocation: '/home',
routes: [
ShellRoute(
builder: (context, state, child) {
return ScaffoldWithNavBar(child: child);
},
routes: [
GoRoute(
path: '/home',
name: 'home',
builder: (context, state) => const HomeTab(),
),
GoRoute(
path: '/explore',
name: 'explore',
builder: (context, state) => const ExploreTab(),
),
GoRoute(
path: '/profile',
name: 'profile',
builder: (context, state) => const ProfileTab(),
),
],
),
],
);
// scaffold_with_nav_bar.dart
class ScaffoldWithNavBar extends StatelessWidget {
final Widget child;
const ScaffoldWithNavBar({super.key, required this.child});
Widget build(BuildContext context) {
return Scaffold(
body: child,
bottomNavigationBar: BottomNavigationBar(
currentIndex: _calculateSelectedIndex(context),
onTap: (index) => _onItemTapped(index, context),
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.explore), label: 'Explore'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
],
),
);
}
int _calculateSelectedIndex(BuildContext context) {
final location = GoRouterState.of(context).uri.toString();
if (location.startsWith('/explore')) return 1;
if (location.startsWith('/profile')) return 2;
return 0;
}
void _onItemTapped(int index, BuildContext context) {
switch (index) {
case 0: context.go('/home');
case 1: context.go('/explore');
case 2: context.go('/profile');
}
}
}GoRouter 17.5 memperbaiki masalah di mana iOS back gestures akan mem-pop seluruh ShellRoute alih-alih hanya sub-route aktif.
Siap menguasai wawancara Flutter Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
StatefulShellRoute untuk Mempertahankan State Tab
Ketika pengguna berpindah tab, ShellRoute membangun ulang child. StatefulShellRoute mempertahankan navigation stack dari setiap branch:
final goRouter = GoRouter(
initialLocation: '/home',
routes: [
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return ScaffoldWithNavBar(navigationShell: navigationShell);
},
branches: [
StatefulShellBranch(
routes: [
GoRoute(
path: '/home',
builder: (context, state) => const HomeTab(),
routes: [
GoRoute(
path: 'details/:id',
builder: (context, state) => DetailsScreen(
id: state.pathParameters['id']!,
),
),
],
),
],
),
StatefulShellBranch(
routes: [
GoRoute(
path: '/explore',
builder: (context, state) => const ExploreTab(),
),
],
),
StatefulShellBranch(
routes: [
GoRoute(
path: '/profile',
builder: (context, state) => const ProfileTab(),
),
],
),
],
),
],
);Dengan setup ini, jika pengguna bernavigasi ke /home/details/42, beralih ke tab Explore, kemudian kembali ke Home, mereka akan tetap berada di layar details.
Route Guards dengan Redirect
Redirects menangani pemeriksaan autentikasi dan navigasi kondisional. Callback redirect berjalan sebelum setiap navigasi:
final goRouter = GoRouter(
initialLocation: '/',
redirect: (context, state) {
final isLoggedIn = AuthService.instance.isLoggedIn;
final isLoggingIn = state.matchedLocation == '/login';
// Redirect to login if not authenticated
if (!isLoggedIn && !isLoggingIn) {
return '/login?redirect=${state.uri}';
}
// Redirect away from login if already authenticated
if (isLoggedIn && isLoggingIn) {
final redirect = state.uri.queryParameters['redirect'];
return redirect ?? '/';
}
return null; // No redirect
},
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/login',
builder: (context, state) => const LoginScreen(),
),
GoRoute(
path: '/admin',
redirect: (context, state) {
// Route-level redirect for admin-only access
if (!AuthService.instance.isAdmin) {
return '/';
}
return null;
},
builder: (context, state) => const AdminScreen(),
),
],
);GoRouter 17.5 menambahkan dukungan untuk menggunakan context extension methods seperti context.namedLocation() dalam redirect callbacks.
Pertanyaan Interview Navigasi Flutter yang Umum
Pewawancara sering menguji pengetahuan navigasi karena menyentuh arsitektur, state management, dan integrasi platform. Berikut pertanyaan yang membedakan kandidat senior:
Q: Masalah apa yang dipecahkan Navigator 2.0 yang tidak bisa dilakukan Navigator 1.0?
Navigator 1.0 menggunakan navigasi imperatif: Navigator.push() dan Navigator.pop(). Aplikasi tidak dapat merepresentasikan state navigasi sebagai URL, membuat deep linking dan dukungan web sulit. Navigator 2.0 bersifat deklaratif: state aplikasi menentukan navigation stack, URL adalah first-class citizens, dan deep links bekerja secara otomatis.
Q: Kapan menggunakan context.go() vs context.push()?
context.go('/path') menggantikan navigation stack saat ini hingga route yang cocok. context.push('/path') menambahkan route baru di atas stack yang ada. Gunakan go() untuk navigasi top-level (berpindah tab, ke home) dan push() untuk masuk ke detail sambil mempertahankan navigasi kembali.
Q: Bagaimana cara mempertahankan state saat berpindah tab?
Gunakan StatefulShellRoute.indexedStack(). Ini mempertahankan navigation stacks terpisah untuk setiap branch dan mempertahankannya saat berpindah tab. Tanpanya, berpindah tab membangun ulang seluruh sub-tree.
Q: Bagaimana cara passing objek kompleks antar route?
Ada tiga pendekatan. Pertama, pass ID di path parameter dan fetch objek di layar tujuan. Kedua, gunakan parameter extra GoRouter untuk passing objek langsung. Ketiga, simpan objek di solusi state management (Riverpod, Bloc) dan akses dari tujuan. Pendekatan pertama terbaik untuk deep linking karena URL tetap bisa dibagikan.
// Passing via extra (not deep-linkable)
context.push('/product', extra: productObject);
// Receiving via extra
GoRoute(
path: '/product',
builder: (context, state) {
final product = state.extra as Product?;
return ProductScreen(product: product);
},
),Q: Apa itu callback onEnter di GoRouter 17.5?
Callback onEnter dieksekusi saat memasuki route dan menyediakan akses ke state route saat ini dan selanjutnya. Ini memungkinkan menjalankan logika sebelum route sepenuhnya dimuat, berguna untuk analytics atau conditional pre-loading.
Type-Safe Routes dengan Code Generation
GoRouter mendukung type-safe routing melalui code generation. Definisikan route data classes dan biarkan build_runner menghasilkan navigation code:
import 'package:go_router/go_router.dart';
part 'routes.g.dart';
<HomeRoute>(path: '/')
class HomeRoute extends GoRouteData {
const HomeRoute();
Widget build(BuildContext context, GoRouterState state) => const HomeScreen();
}
<ProductRoute>(path: '/product/:id')
class ProductRoute extends GoRouteData {
final String id;
const ProductRoute({required this.id});
Widget build(BuildContext context, GoRouterState state) =>
ProductScreen(productId: id);
}Setelah menjalankan dart run build_runner build, navigasi dengan compile-time safety:
// Type-safe navigation
ProductRoute(id: '123').go(context);Ini menghilangkan typo di route paths dan memastikan parameters selalu disediakan.
Menguasai Navigasi Flutter untuk Aplikasi Production
- GoRouter 17.5 adalah solusi navigasi yang direkomendasikan untuk aplikasi Flutter yang membutuhkan deep linking, nested navigation, atau dukungan web
- Gunakan
ShellRouteuntuk bottom navigation bars persisten; gunakanStatefulShellRouteuntuk mempertahankan navigation stack setiap tab - Konfigurasi deep linking spesifik platform (Android App Links, iOS Universal Links) secara terpisah dari GoRouter, yang menangani logika routing
- Implementasikan authentication guards dengan callback
redirectdi level router atau level route individual - Untuk skenario interview, fokus pada penjelasan model deklaratif: state aplikasi mendorong UI, URL diturunkan dari state, dan GoRouter menangani terjemahannya
- Type-safe routes dengan code generation menghilangkan runtime errors dari mistyped paths
- Periksa dokumentasi navigasi Flutter dan changelog GoRouter untuk fitur spesifik versi
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Bisakah kamu menemukan bug di Flutter?
Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Ditulis oleh
Anthony Fillion-MailletPendiri SharpSkill
Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.
Diperbarui 23 Agustus 2026
Bagikan
Artikel terkait

Flutter Impeller 2026: Arsitektur Rendering Engine, Performa, dan Pertanyaan Interview
Flutter Impeller menggantikan Skia dengan shader yang dikompilasi AOT, menghilangkan jank saat runtime. Panduan ini membahas arsitektur, dukungan platform, benchmark performa, dan pertanyaan interview.

Flutter Custom Render Objects 2026: Custom Painting dan Pertanyaan Wawancara
Kuasai pipeline rendering Flutter dengan custom RenderObjects, pelajari kapan memilih CustomPainter vs RenderBox, dan persiapkan diri untuk pertanyaan wawancara level senior tentang siklus hidup Element-RenderObject.

Perbandingan React Native dan Flutter: Arsitektur dan Performa 2026
Panduan lengkap perbandingan Flutter 3.44 dan React Native 0.86 dari segi arsitektur, performa, state management, dan pertimbangan pengembangan tim di tahun 2026.