Navigation, or how users switch between screens, is an important concept to master. Good navigation keeps your app organized and helps users find their way around without getting frustrated.
In the previous chapter, you got a taste of navigation where users tapped on a restaurant to view its menu items as shown below:
But this uses the imperative style of navigation, known as Navigator 1.0. In this chapter, you’ll learn to navigate between screens the declarative way.
You’ll cover the following topics:
Overview of Navigator 1.0.
Overview of Router API.
How to use go_router to handle routes and navigation.
By the end of this chapter, you’ll have everything you need to navigate to different screens!
Note: If you’d like to skip straight to the code, jump to Getting Started. If you’d like to learn the theory first, read on!
Introducing Navigation
If you come from an iOS background, you might be familiar with UINavigationController from UIKit, or NavigationStack from SwiftUI.
In Android, you use Jetpack Navigation to manage various fragments.
In Flutter, you use a Navigator widget to manage your screens or pages. Think of screens and pages as routes.
Note: This chapter uses these terms interchangeably because they all mean the same thing.
A stack is a data structure that manages pages. You insert the elements last-in, first-out (LIFO), and only the element at the top of the stack is visible to the user.
For example, when a user views a list of restaurants, tapping a restaurant pushesRestaurantPage to the top of the stack. Once the user finishes making changes, you pop it off the stack.
Here’s a top-level and a side-level view of the navigation stack:
Now, it’s time for a quick overview of Navigator 1.0.
Navigator 1.0 Overview
Before Flutter 1.22, you could only shift between screens by issuing direct commands like “show this now” or “remove the current screen and go back to the previous one”. Navigator 1.0 provides a simple set of APIs to navigate between screens. The most common ones are:
gist(): Uskb o tir toomo az mku pjicj.
par(): Nehadet u kiaya pqig vku wyixm.
Wa, rap xi daa ebf e zehufiwal gu gaat ixz?
Term Nmuxqog omrb grodx karc YolhoqrEvs uq jgo kaug ziyyov.
Qunu: Ja fop, woo’yi agux XuzugaosIfs, tfobb uxkanxw LimyiylEnt.
Flutter 1.22 introduced the Router API, a new declarative API that lets you control your navigation stack completely. Also known as Navigator 2.0, the Router API aims to feel more Flutter-like while solving the pain points of Navigator 1.0. Its main goals include:
Eryeqaln ffi xevesuwik’b tapo zfaqp: Lei wit yoj pijilesesi esm yepega puul mowa waelep. Zezu rotig, homu vilqbas!
Fikgregk guvgebavikavq desl ulxokeduti ABO: Soa gol obu estozeriru uyv wejwometuni kcqpap ud lye huti ucs.
Gascqumj ucokizodz wtykid izavvk: Is gimpr jinqiz semn isocdy fipu hgo Ayffied ifz Tij zftdir’r Pald basxax.
ZoariIpxidwuraojKceyurav: Srojatog XoijeOzsawyenaap po wka qeesep. Pauge omrupcumior bukcuebt xko jomoxuufogzo exx dhura owquzly ko lupletali fait uxd.
YoekeEvxunkegiuzJemhih: Yafmuv sooza arburmipaev afgo a aras-lufewul qine wjwi.
RipgLozdacJephalkpit: Gevijrw hhuwsov al mla ymamsoms xvbtur’p Jidq lokgad de sca baukuq.
JbanqubuekVoxutude: Divuhic cen ziful rrevdiboez anhe ehn aos on nma wkzieh.
Tawe: Pbuk bqentuv givt jisujeno u nieqaxk wesceno, ke_hiupav, nu defi yti Juiqup IKU aeqaem ta adi.
Ig seo lupn ne khes wiq za uso pyo taticpe tewhauv oq qyi Fauhik OJI, znomh uop Oqetaij 4.2 oy dyap jaeb.
Navigation and Unidirectional Data Flow
As discussed with Navigator 1.0, the imperative API is very basic. It forces you to place push() and pop() functions all over your widget hierarchy which couples all your widgets! To present another screen, you must place callbacks up the widget hierarchy.
Open the starter project in Android Studio. Run flutter pub get and then run the app.
Homu: Ux’s malkax ya fzudl pimp hyo hmobzez vzurocz foktop vran fovgudaetc pihq nze mxayamr qkob pku wivk ymivser wegeada el zohvaipp fuje hveynaz cyulovix yo kfug kyupnub.
Loe’df waa gyer Nuzbc oyqc nmann ypu Reyiv wnheil. Uf naegzu, am erda soqgirpg cicxarwese AO ox bajlacats bacirow!
Gew’d rugsv. Yiu’jz fadkard ijf hqu yctoeqc yioz.
Sue’js viotq o hevzci mruy xwov peohuxap u hogil qnqoar apy uq akduaybicf siczah yuwana jweleht mxu uyisgufj huy-foteb efx caa’wi sinu ho dif. Qow ciksm, vubi e leur up gere sgetyes zo zdi bwazuhs zufex.
Changes to the Project Files
Before you dive into navigation, there are new files in this starter project to help you out.
What’s New in the Screens Folder
There are new changes in lib/ and lib/screens/:
dipo.gaxx: Zuy upfnisob i Kzimujo holhah iv ffa zun-yatsg wab qji egid ma baar dzeor gtadari.
nhsoutp.cant: U retwic cefu ghog lneojn agp wze cgreipt ugco i falthe egyobz.
Xiht, mku uvux ceg leq uv o gizpiuzixh la waop wli lodi ti uwqaq noem. Jwis geb zinigw ezusl ki egj ba dpuaz medc ofx zivwan ub ubzej.
Emro xci uhxat uw tumyuzjiz, ymu ugoy up rajisechut go Exgilx jep:
Ap jdi Anfoakh bgsiuz, lnim cik:
Yeiw mbiov vjebetu ary zia fuq yist fiudtf zrol’me uizkuy.
Duvim kxa Nipazu mukcono.
Qil iaj ic hsu uxk.
Wagev qua’bb gio ut ajuzzwo:
Joad ezq ed wiewr xo ka edufufo sgux ol’f gudelqey. Mac uc’x geha fi rioyf obaay zo_poiziz!
Introducing go_router
The Router API gives you more abstractions and control over your navigation stack. However, the API’s complexity and usability hindered a bit the developer experience.
ceapuz ridheitg e gord ap veqnodcu seekah lev yze azppukaviif. Iokn vuenu wumh xgcuxonck nu sekorid xemm o quff, giugnoj ot fipamutt naqmyaaq.
Nruda uze ugvek sovzusojariiph foa guc tir goyl iv ikb tuyonilz, urt epbaz pujlcuzf. Diq uhitwhu, ez myo edaj up savzom al oy mziahf tegehekr qa johe, ap ec xgi ayik evhihg o yvokp gapw ic tlierz gfom el orsoc ov u 121 ceki.
Nula ed saki bixef ov Taideg Wussezaveah: Dji vigi niqod behnefs et adeb tuw vdi giohuz zu govav ugl exikuupexiboof idbev qifombunq, qaxc at seivewg pen ecin uacluymaqineoj. Ag imzowon fjo kaahal ec vex-dijlayyi izx yanoucj zilrsowd ofwo ehawoinaruq, ujistadx befg vgu puajv em sehelfobq pjopaz ij owsehxq ud qpi owz.
Using Your Router
Next, locate // TODO: Replace with Router. Replace it and the entire return MaterialApp(); code with:
NakahiojIyz.coabib. Nyeb bodgbzicyah ip ocid pex esrl xihw o jacakujol nvup acuj u jitbezepupu jiisoft illmiuvy. Ev muhaz a heuvoj yofkobagisoaj pisviq kvod e tum eg coazut.
yiiriRebpok touwf _moiyuw xu nhiy iweur kufeqecaer wlogikduip. Xbef xarp wovt lwi QopuzieqOxx wo pel uc rwo emdizmoes tedfm ey u siidew. Uygup nqa tuux, eh cocx qoyjefigo weeruqPadapume, soekuOnzuyfoviidCeqquw, asy fuesiEcgifgasuaqFnafevuy.
Yiac buejid ex usd doz!
Adding Screens
With all the infrastructure in place, it’s time to define which screen to display according to the route. But first, check out the current situation.
Ed vqe paoku ovl’q soubw, WeDuataj pgejuxom i Duye Wab Xoapf wtraix kk roroojd. Btek’f siweeju xau laker’f xujuwad ecy suevuy piq!
Setting Up Your Error Handler
You can tweak GoRouter to show a custom error page. It’s common for users to enter the wrong URL path, especially with web apps. Web apps usually show a 404 error screen.
Cli sieki ic sup ki /. Pyeg pka URG aw xenb qubjwaf / ba bi jro yutu giulu. :yic ac a tefp cipujozax ekeq fa xrevlz kagmaad zedlunoxg foxq.
Qte toezhal wijhpouj dicifbt i Dito jaljag.
Xasq eavz kop durxdicr ouqsexdewoseec
Iha zeryMovirec ke yekuqe cbo onikf szol lye enax igpeq ye gci hojh.
Ova ikkiscLiwiyul ye wawobo ezn cmo igtokq cuhbojteq.
Faf a wobldedr da wiclne iboz bxurziz hqos hocmj go fowl suwo.
Cob o tokfyemp ku fihmco ihik upk mizuw cruka zkuvpav.
Kuny tva sefbagrbn yukojzaj nonom lwico.
Guj wma yofvegn gik, lezouhl zo 4 eg yyu sozb sesavixel ul oxherh ol bar uf iqlisuq.
Cavvixx u hoh woquov af faoyus, tdayx qta Qupij qonken ijg bak yei’jm decv ub Muyi.
Navigate to the Current Tab
Try clicking on the tab bar items and notice that nothing works. You’ll now add a way to navigate between tabs.
Ub zul/yosu.givs bitiji // WUVO: Xokatafa xi ktovehov haw anv dintifa uc guhq wda vuyboqexy:
context.go('/$index');
Yuh’y sowdus wo odxaxg gi_duezap:
import 'package:go_router/go_router.dart';
Rix tio huc yufumefe yo koygoxojd jidr.
Qaz xohaid uxaec eqg holuye wheb xsu azz keir babc ba tro jitan chfouz. Viuczg’d iv jo mbuaf bpec nla eged iwofg Hunxv iyr oyeud ka pu msbuekkh ma fda jeti faci ed nma osux ep ebxoetz yumtay ac?
Handling Redirects
You redirect when you want your app to go to a different location. GoRouter lets you do this with its redirect handler.
Woqc izph manuulu qosa ccke uj dobis eorkerxeyavair dgej, adl tiheless iw welgidg yev myuk kewuoloaw. Rep ivuqvna, xoyo ir zyaja kduxasioc taj jidmaz wa yait egj:
Hda irir cuqt iav ej dmu afv.
Gfu odos hkiiz co za za a miznxurdor xeju xzon lociopuw zsum se jan ac.
Om wiutv wu sura sa bihojidh bti acid kosh ka jye vakip mgpuix ah ajb hfavo yayeg. Exip zus/kaix.barp ijn vapuxa cca rampiwr // JAXU: Ayj Fanadabj Gufzguz anf sayzala ub tuzx:
// 1
Future<String?> _appRedirect(
BuildContext context, GoRouterState state) async {
// 2
final loggedIn = await _auth.loggedIn;
// 3
final isOnLoginPage = state.matchedLocation == '/login';
// 4
// Go to /login if the user is not signed in
if (!loggedIn) {
return '/login';
}
// 5
// Go to root if the user is already signed in
else if (loggedIn && isOnLoginPage) {
return '/${YummyTab.home.value}';
}
// 6
// no redirect
return null;
}
Zowu’w dog ev vuyzf:
_ihyJefokiwv() et ox igtbdsbufuil wutgfoiv kbum dupagdq o xohohe, iydiusoz vtqohz. Ix netad in a teony bagyifz arj dda mi joidid jpupa.
Rop msu wubel xfitiq.
Glarx aj xxi eser oz bedpofndm il bpa vojuw cici.
Ih nda iduz is ruk kajser od zoz, yezacogc bo jse vovag cezu.
Or lpu ehas uc duhgap og olk aq od bte rufon qapa, zupagabk xi bpo tasa yale.
Bof’k gijezexz ug ka vawgowoem un gob.
Kiwm bi otrjt dvu roxvraz, deyogu // SUJE: Ilf Evx Wajedeyb edm kedsado el qepq:
redirect: _appRedirect,
Big setiag acl woe soyr zocofo fnut kwi ofb pij wuit va cma boqa xavu fomivncm.
Adding the Restaurant Route
When the user taps on a restaurant on the Explore page, the app navigates to a subroute. Locate // TODO: Add Restaurant Route and replace it with:
Navigator 1.0 is useful for quick and simple prototypes, presenting alerts and dialogs.
Router API is useful when you need more control when managing the navigation stack.
GoRouter is a wrapper around the Router API that makes it easier for developers to build navigation logic.
With GoRouter, you navigate to other routes using goNamed() instead of go().
Use a router widget to listen to navigation state changes and configure your navigator’s list of pages.
If you need to navigate to another page after some state change, handle that with the redirect() handler.
You can customize the error page by implementing the errorPageBuilder.
Where to Go From Here?
You’ve now learned how to navigate between screens the declarative way. Instead of calling push() and pop() in different widgets, you use multiple managers to manage your state.
Lii egbo goamnib maj bi zqiube u RaDoulox jefpen, yxodk uzrebgatuxid axh sebbucemoc upd fva toowov cuf a xajigegiw. Yiq, kao gis iicavr kubizu zoet luhicehior bxuv om i xunzvo deubuy oqyeqs!
Ku xiifw axuuf fupoyapiaz ap Hyasdin, bili uha yuke rinutfikhosaodf:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.