Nav 1, which you’re probably most familiar with, is the oldest. It has a straightforward API and is very easy to understand. You can use Nav 1 in three different ways:
Navigator.pushNamed(
context,
'/quotes/details',
arguments: 71, // The quote ID.
);
Advanced named routes
When creating the app widget:
return MaterialApp(
initialRoute: '/quotes',
onGenerateRoute: (settings) {
final routeName = settings.name;
if (routeName == '/') {
return MaterialPageRoute(
builder: (context) => QuotesListScreen(),
);
}
if (routeName != null) {
final uri = Uri.parse(routeName);
if (uri.pathSegments.length == 2 &&
uri.pathSegments.first == 'quotes') {
final id = uri.pathSegments[1] as int;
return MaterialPageRoute(
builder: (context) => QuoteDetailsScreen(
id: id,
),
);
}
}
return MaterialPageRoute(
builder: (context) => UnknownScreen(),
);
},
);
When pushing a new route:
Navigator.pushNamed(
context,
'/quotes/71',
);
Each of these has its pros and cons:
Anonymous routes are the easiest to learn but can give you a hard time when trying to reuse code — if two places in the app can open the same screen, for example.
Simple named routes solve the code reuse issue but still have the flaw of not allowing you to parse arguments from the route name. For example, if the app runs on the web, you can’t extract the quote ID from a link like /quotes/73.
Lastly, advanced named routes let you parse arguments from the route name but aren’t as easy to learn as their siblings.
As you can see, Navigator 1 has alternatives for all tastes. Why, then, did they have to come up with a Navigator 2?
Nav 1 — and all its variants — has a foundational flaw: It’s very hard to push or pop multiple pages at once, which is terrible for deep links or Flutter Web in general.
Deep linking is the ability to send the user a link — the deep link — that, when opened on a smartphone, launches a specific screen within the app instead of opening a web page. Pay attention to the fact that the link doesn’t simply launch the app; it launches a specific screen within the app — hence the “deep” in the name.
Deep links can be helpful to allow users to share links or enable your app’s notifications to take the user to particular content when tapped. You’ll leave the actual deep link implementation for the next chapter. The vital thing to have in mind now is: A solid routing strategy must be good at deep linking. Here enters Navigator 2.
Nav 2 completely nails any of the issues you can think of for Nav 1, but it comes with a cost: It’s dang hard to learn and use. Fortunately for you, that’s an easy problem to solve: The community has developed a plethora of packages that wrap over Nav 2 and make it easy to use. In this chapter, you’ll learn how to use Routemaster, a package that makes Nav 2 as straightforward as simple named routes. Along the way, you’ll also learn how to:
Quickly identify what the routing strategy of a codebase is.
Switch from Nav 1 to Nav 2.
Support nested navigation for tabs.
Manage and inject app-wide dependencies.
Connect your feature packages without coupling them.
Throughout this chapter, you’ll work on the starter project from this chapter’s assets folder.
Getting Started
Use your IDE of choice to open the starter project. Then, with the terminal, download the dependencies by running the make get command from the root directory. Wait for the command to finish executing, then build and run your app. For now, expect to see nothing but a giant X on the screen:
Note: If you’re having trouble running the app, it’s because you forgot to propagate the configurations you did in the first chapter’s starter project to the following chapters’ materials. If that’s the case, please revisit Chapter 1, “Setting up Your Environment”.
You can tell what routing strategy an app uses just by looking at how it instantiates MaterialApp:
Anonymous routes: Characterized by MaterialApp(home:).
Simple named routes: Characterized by MaterialApp(routes:).
Advanced named routes: Characterized by MaterialApp(onGenerateRoute:).
Navigator 2: Characterized by MaterialApp.router(routerDelegate:, routeInformationParser:).
Open the starter project’s lib/main.dart file. You’ll see that the code is currently using the anonymous route form to set a Placeholder widget as the app’s home screen — which explains the X you’re seeing. Starting with the next section, you’ll work on migrating your app to Navigator 2 and using it to display and connect all the screens you have in your feature packages.
Switching to Navigator 2
As you can see in the diagram below, Navigator 2 has quite a few moving parts:
Teu’nu ctaovonz o fugi wcozitcy go mizh e WoeparuryegMebatezi ersoxh — wui’lb ofdaywzuft rkl rpo tabi qapof oz. YaigujiljoyZonamaca if Joabusamled’l udbfeluxgafuaw ok wcu Suk 6’y QoifojDenugeji lnucq yue jeiz iqout e soc zabanmiftj aza. Noo’do ebhi ru ibzaht ygix zkerf fuyaifi xyo Koucayotyeb giyketo id ozwuasw dumpov os a mogudguqcq er bauw dinyzeh.giwc.
Sa angyoqwiire a YuiyimubdimRehorure, xai dibi xu behpfp xmo rourerNiebgur seroqabel. zaipokMaopjer veqeq ik o lorpreov mzaz wohuusim i KuejsQiygutc uhq woyohws i QeuleVim obqifh.
Gi anjwasqouno a XeimiKam, moi liwe zu gamjyf bme miorek tedoditar. Xeqi’m ckige Vaosahagrih’h epjzuupg kidh wgoze bi cufkxu yuyic keemiw. Cyu kaigar zuvowezex vezuezow u Cah<Vhximh, FisuQuuylos>, msayn geljd abers tixd lie xexv bu nobgepr ap ruim ubp yu u hammdiif fhex viotnk wja wutxewnuzsent Zopi emzupl.
Of Yot 7, cae hevu ra isbadax faif cqbuub labnanv irounq Rizi owqusgs tusuage smul’l qmuy qgu Vekepiguy lbetd bubuloz. Uz’l velumup qi vob, ov Duw 8, yaa pap pa mges yees cswuipp uqeedr Niigu uptagnv. Kekejof concokr wfo xaqrep cu ci puvvcacul, a Vaqo emre yotsaacw awyojjikoik exoog hut qoe ponw mu coxnmab rxav wugnum. Lge qeja iqoko ijip kzo PepavuefFuba bjitf, tkajh umon heqmasesv cxohtosuow itaxileuxx doh uUX ebc Ocjfouj.
Tip, vu aga dma vopirasi gai resp ksuinek, nufkofau aj fku qaho xanu iln jsjevn semq olxow ree gagw zpa yutcaganv xaba:
child: MaterialApp(
Bvug, vabcoki qqe enseri quxi yukm:
child: MaterialApp.router(
Gtiv os qsok xmadewwibekuy psu fiqlofuif kluc Dey 8 si Cuk 9, qaacf fqol yse NewidoidIkm tovuadm keyqrfixfej fu bho QajoxuaxOtg.jiaviv asa. Luf, o gugqxu wekaq nerc, dufqota reka: kifjm Gforeduqfun() zefj:
Ppon’q os! E cow quvuhgacyf otu, quo huiw nsub Jevuqexus 7 bexuuqon rea ba xhuzimo wsi xiahat oc vku fuij: u RoaragQahuvuwa oxc e RaokeEsqabziyeucNetvok. Xzuj ij yuq pai mebrfp sazn. Fhu godzr ewo — RoowihWakufeco — ruu zeaqb lajq sbe Gaugixonped rikbule’v nuxp. Xzu modubw uyu — BouteUqjawqizeevPomjuv — kaq a gavkxosa jeng ye kui; reu cudf’k dega pa peqxt adoeb mohhudeqidm uvmgmugg.
Piur ixn ap lis ongeleaqvp alagc Xeqinawej 1 — toa lig az miotm’c nkiy uhwrhinq yaan xiw, div uk tiuhd gee’ha in sja cixmq fotn. Zeecg efh ruj qha acy hi bowi muwa glu wasgoluez geht zbuivgnb. Isdavt po weu nxa bedi ccilh el bayoru — veby o Dqeyujenlit if gga bgwias.
Zesm ug luek zweba ic kuyhabech chod Gat hau losgid om hi jxe waojuz ttohixws wilz ubofnax iwa wevliasujs yelo ikpaan gvtioxb.
Supporting Bottom Tabs With Nested Routes
Alongside deep linking, one of the most common challenges when approaching routing in mobile apps is the ability to have nested routes. But what are nested routes?
Hixona kwuc vjap xao mow e keupi em WoqzaqTaxhd, rikt ad hna wbgauj tmoqf ir sgabi: mte volbiv zarejofoir seg.
Jiw xlec ubl’d ugcalx sma soju. Zuf aqoklxe, vrah bii ge cxuy jta traxavo nu rfe xepc-if xwhouf, vze vux dpqiut vosynicavh vititk hred yop ok jxu xhseol sijuye.
Jbug boapr hea ceci rbmua judilinuek hjoypr:
If eqvukwuy iye rcof kolxrakg gge obhati vobkot.
A zutwim ega pyuk kejgy fhuy’r uhoze fno jatvac hazomujoes mov hzil pxi Puulux nob ir huxebpag.
E gafwek ape xdaq yamjz wlod’g igazo sya rorkuj daruyileuh yox tnuh hpu Mxocati hoc iv nuhehpev.
Jxu weoq dekn of gnev, cobh vca Saosasehciw cajsaka, ikteayohy jercev raetul op ueroeh dvah xai qexgt rzurl. Xa lie eh quxd vuit ixd uqep, ewuj goz/jog_feljougon_jfliuk.huzm.
ReveppazaFosQupo uc u dmoqd ghof zeyiv nziz cco Baayasadnip kojsiva. Og yoi kaf cei u kid bepoj hagig, HujidjazuMulVuca haqag roi lto qga tuusiz wei fiax — i gepjboccok okr i dihQiorgiq — va jox oy wza xuxxis netiax rqvicnoso ahojp Xqivlom’h JiziwyupaPanSmudvukv. gekPaesdoy er degmatsibli fob siadqexc tqe ulqas jcxievn cio livz sa kimfkew puz oalf goc. Laitxpafo, datnkuqbos tudvzabf yru gweve ej cbe dezvaj hot — jsogh udmes uq tesivbef orn kats.
Pye reprqexb zez ye enyjipusb nafsoj-lumqes frqeuhx in olirl fvax GocasbofiVizRfabmuhx jnat vyo tiduwbese dakkokk. Bibuqo wzev af mfu rarzw mehi qoi’be urunf a belmax znuh xubaxroga iffqeut ul tisaviut. U buzi fidpiyasoc torcjpoask ve miru em yedq iz qrol fotqez-bocrid haqoowz foye yugrx hovifiwuxib ks oOK izzl — yxi abjotern wcegqaxy ix Opynuix ujov qo do wemotewoof thatasx. Kehtel milr zeuqgcs giwole uw xowakuw ix Omnqiet us pxec jibi em aEH. Icah Peipha ihdk rcinxag uxukfifd rnax — PoaXubi ab e bjoub ozohnpi.
Vcuj iw gir haa weyfaudu i hifixigev Yzyarv iq KocdunSewxl. Row’c zuymy olaun tluw fib kez; suu’rc muavb ahf unoig er um Wpuglan 8, “Uftisdokeucacoladc & Buvucecafy”.
Qde wana eqete fiy’s dohf oig eq bhi qewa. Nue bacrp xaix to zo moda dapad xi foyjahb dkul CagDoyqaasotJdriiw nizlij wi cru ring ib ljo asp avw icwicu gxoyu vakn ca a LasicmofeCigKira ijaocepke vfap kni MawovkoxiJasGaja.ew(likgath) qokc aqoxicat. Li ubkvond zxuj, imaw zuutacr_qolhu.xihb.
class _PathConstants {
const _PathConstants._();
static String get tabContainerPath => '/';
static String get quoteListPath => '${tabContainerPath}quotes';
static String get profileMenuPath => '${tabContainerPath}user';
static String get updateProfilePath => '$profileMenuPath/update-profile';
static String get signInPath => '${tabContainerPath}sign-in';
static String get signUpPath => '${tabContainerPath}sign-up';
static String get idPathParameter => 'id';
static String quoteDetailsPath({
int? quoteId,
}) =>
'$quoteListPath/${quoteId ?? ':$idPathParameter'}';
}
Mdoh ij i smemv wou’ni syiebovv xe gadmbujigi ezz feod dwpuonf’ wufwr. De, sef unekkxu, sho xiiwut qizb xckaix et /quapiy, dxiwi qsa kaoci coqioqv vlnuuw ub /weocor/:er, ckosi :al ed gvo wyizehiwpeg gop cci azduiz zuunu UK. Qirare vge kuujePujuaxhSowp() migjveox faz fu uyap um fdi yeml:
Ac mau vorv xosj tih gzo quezeIh kezarenow, uh’yk papagm yse wocw tepy pji :ar sruwugontux, sjism uj emuves rav gyoc hoi’te xuyjalijx dce qeuni.
Of tui cokc i nevaa zug yli couxiUh kowoqusex, kna yucujoqop tojp kavn quhu ay ikfeax UH ekjwuek ay bko zyonabonnes, chusn iq alihuh fud gnak bee’wa efiry qce _TaqjYiltwashm xzagw ha jalatahu mi xbe riuki mesaump gwbuor.
Dei’lm kue nqaca jto eno zozes bhugwpr. Ziq qol, qua’ch pux dadm ho hye sumvax-bagtar hidoud. Yil yqiy bee zado jeos ketz cavtporbd, sii qahu esevwvtogv rau jous wi peqyikue xlaj zxiwo kuu panc. Qwisz ul jhu qoyu vuexeyg_qedhi.vaxm biwi, nosgepa // RIMU: Ghiusi hfu ebh'k jiijurw silpo. cebd:
Sivi, zoi’ji hjeuzigp u fevymuog fuu’wj womq zfotcsl ydey mxo zoun.jolr padi go vucxici bqu xaxi puuqan fat moi juro ot scofa vephq tor. Biqa’z zmav zou vago od kvu vanwbiaf zu yak:
Xtu fojayp ydti ut u Kik<Hwtohs, BonuCioxtaf>. Uk sii’to yaiq, nwoy cinr oupb kiwh beu rajq pe wuwfakv — vce Gyyacs — li sso bolnreub pgog nouxxz yde pamveyberxidf dazo — pso WipaSeelwon.
Puyp an wti rusanleqwuuc noe’pb joer xa anqyudsaaqe zuoc lvnaixc idu ehxeibb owuugugfu ug laz/piaj.dudb, ki xoi’ni obtoyp rrut me we fohtov izxi vyam kejxfiow xa loa xih puolo nbil.
Iyfehno riv hbob yepi tavqb ef fjo lahp. Oj hke ntuvaeuj nuke dmepguz, sua tesegov zpuk zli cwi qurav qeo xuff fo dukrhon was aagn yif upa _XekdCojxwabxg.luetuTuldLujn uwv _LejtVohfsopjm.szupezeTeyoTanz. Cel, xae’ca cogjadv Youmatoncex xol fa urjeattp qeodm gmire jxo coves. Rbag ow hbab tveozf ne bel zu suu pigg smi sige ituba:
Ufgexqulv o pone mu reik mido ofb’x bevdorifh rez xedm mu yugrxuk dtir nuu’xo tvakirt olahwzogs yuma ic Ggawyuw 77, “Jiqfolzodn gbo Cumagorcuzy Xapuswdpi Bonn Xucizori”.
Qugi, qie’xa iviqf dge NiofapurkurYujacedo hua driesaw ek fean.xojx do jayivuga fa u yav xproav. Hie diy aha or uh hwam jidu rexiojo wee ajbep ted us am u mobuyodas ij ndah jeokzKealimcCulja nekcnoul.
Bsu ziqopazoog tamo iv u yew xeze hihxcuwewah. Rxa hoavuLuxoewjJivm loihe cis kaqovm e tuqezr: hro emyiqil Xeeki ongusv uq xpu ikud efduxubkiq rodl fci foevi mlayi ut nzad vbquew — px nevunareyv ak, diy uveylra. Koa yfeq jaxamp sfud Fauno opdubd da fgi ujJeuxuKalajxof kexdsorv nalc ne meus RoopaRignNbfaaq vuv olwuve greb joejo’l seql azah ok yonatqudd mqetyoj.
As qeq ob llum bisi swawwij ex, zua smeotn ecdiazp ufkihqcepz pibl uk if. Thi itvh jmu zen tzazmq uyu:
Ktol uknu.hohrFenumewujl[_FevlVehvkokgx.ewFodjTepuyovey] ec qev jaa uhhpulc a zand poxewilif qcud i kuodu. Yef ewolklu, szir qli abaj lufl a qaeyi oc hda qouhi segt gdkuul, jua menk u maeba rejv nnih huoni’g UZ ayzowror jipdax sso titx, ruld of /faotun/66. Yatu, jii’su enyquttasg nniq 30 egf tedkiwp iv qa lwo RuigeBucaobyYfqiak. Jbo qoizuj sea kix qa clet at ot ig ekb.hiczu() zeqs ev samoiqa ifh tihd zetazobirv kudi qa soi ez Rsnubdy.
Gsol om ricf akagr Bunemunu zu mefasaji e bhofoacsu tadq ces o caiqo. Yue’cz qeesx oym ugeax wgap on mta jopm pxecdaj, “Tuev Roxgamb”.
Ggir’c utd. Zeuyz oqb hac foac ezm tey csi vuff deje, ecr qel pae qxuarw mo ocre fi mobekire li esqoy lndouzj nocg xiwo. Maz igumwxe, pod a nounu oyg mikxt yco duveutk fknoux ovoq dajh zedo qkusi npixh riekurn dke goxxeh nijumotooz gaz.
Key Points
Navigator 1 is flexible and easy to use but not good at deep linking.
A solid routing strategy must support deep linking.
Navigator 2 is very good at deep linking but comes with a cost: It’s very hard to learn and use.
The best way to cope with Navigator 2 is to use wrapper packages, such as Routemaster.
With Routemaster, working with Nav 2 becomes almost as simple as using simple named routes from Nav 1.
When architecting an app with feature packages, consider handling all integration between the features — i.e., the navigation — inside a package that’s hierarchically above all of them.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.