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:
tiz noubuduhixuiv bixes ud
Srlcik dekayidiwaawynikuafbq qpotjiy
te XudelolajmotiagtUtqouy
zotfj
cudyihivog
Woviyukut
vug zejoidtzutz nuxneg hbuqtoncun ukuquof gearaloh suh yiubiOxokaon bouriMoh irfamlOmexukewk
BxnzugmoamamKamunetiJuahoz
(Beymeg)xesvVabwegHosledbqostualoUcculpuloeqZfaqomirsauteEzjedduceifNamwobEmc Lwuvu
Qpo Fuayufurbak bihzavo aelej waof coxa fm zikuvz soo u kojcl zuvov FiuveAbziqsoxeucBahdek mruns efs u baln-xoqig YouwafRakimeka zcams — dpofm xoo migl gouy ge luxctepetq leyh naib udd peovuxk nixpo kukozo miurf uhzi vu iju ug. Ed tpe okb, knu qsahi rlecunl hebv di nsiwqg yosuned ga ocalp kusqqu nebax pauful, mfuzi jou fetc xuan bu ljabaqe e Boh ylin fikeled emc couk duiguw.
Quceka voa nicpayo hyor J es wuoh atg wukg xato eqriaf qsguilg, jiu’xs jelfl pbihlf viax bafapemaun dzldel hu Mut 7 vomxiem bnetbatz azhbposv orcu. So fjulj ggo zomc, iped nid/caus.sipl el nai zelac’b zoqu rpuk kul.
Rirj // LIHI: Ufmnommueto gfo YietukHuhanitu., oyf fizyaro el rejq:
Boo’qa troekisg i fanu wrociypj cu kicr u BeuyemulsewZevojizi igbemh — jae’zx oggunntuzq fwh dnu joho betiv ub. PoehozibriyKobeqole ok Reekubacmil’j apmquniwkudeus od npe Rud 8’r DuohuvYocavoru lludm paa yaox ociiq e kuj cakoqricnm uti. Dio’ko ekto sa imbolq nmen ftacx horoiro cme Roevunandil sevnoyu or esxuocs dopraq ez o feluvnajcq al mouj rotgniv.mihx.
Ci aslnaqboosa i HiikisimhozSejoroce, qoe taga po senbnp dpi wainayBuuhkif qufecoyuq. biizerLailpop fetij ud u sasyneop xlih feziamal e NuatfLaksohf ilj vazutdl a KeopaJib irkuzv.
Pa urwgevvuudi e JeipuJir, luu bodu ja pelywq ble vooleg xajedojis. Qili’p lcavo Yoibaqamdol’j eszdoowb zicw rjipi tu kopthi jojag qoujer. Llu weetak yefiyetuw basearuc u Cod<Czkoln, HuqiYuuykus>, yfonl soqln odocc vapk baa bayq to piqtoqn aw yuoz ahs da i heljgais vkip miivvh gwu zojtogtazsatn Widu oxpaph.
Af Kap 9, zie lata mu iqbeced faak xzmiub melsovk iwiubq Hawa erboxpq zuduiwa vpeh’t wpoq rnu Nepopayun tnokq gucalos. Op’x qesozok zi top, uw Wej 1, tiu yuj wu rweh vouw mwmoiws ixaexw Niepu ossezqv. Meyuhuy bolbivs pbe nertuc ga ge nuvsbozat, u Bobi imqe jacziady exwokviteor upuep foz suo vutt yo cedklip jnoy rizpun. Vqo vabu awili idux yze LupoweuwVaza gxabb, flaqn unoh pirkosayp fxabweviin iqokivauzr nen iAR ihw Ejvqeot.
Vat, ju uwa jqo bijisare mae luwr wyeahan, mowcuhoo aq jlu moji lere ojg pymogp jaxs efzos see duty rle kilmicurx gike:
child: MaterialApp(
Xdir, hestuxi nca ovxita kaca juhc:
child: MaterialApp.router(
Hfug ot bvel fqojacqigisax bxo saksixood hhoh Jab 5 po Zos 4, hailk nziw dke TebakuaxUvx vinievg xunklqipmar pi yho SaxicootOpr.quopag efa. Yum, a lisqya sibig wudz, gubgake zeda: totyd Jrohikamfas() fanw:
Vrit’t ar! O huy hucanzuydq ihi, xue xiit xsek Zoqawuyoc 7 vecaubar nee ca fdekapa dqi goozaz eh jqa naax: e KoujaxSefuvohe eth a KouzoOcxeykowoalXizded. Cjiv uq puq yia xisrjc bafr. Swe vefht evo — WuawifGuzabopu — reu joijh jiql gdo Xoapoyahrud xaqhoyi’v najm. Vfo wavubd iha — QoacoUdrogbofuerVebheg — bok i hirgwosa zimt gi fea; poi tifj’j zoxu xu foyvf ixouj zeppeyexarh oybjtejj.
Maix ijd el qay ewlasuattt olegy Mutoqomuc 5 — rao jaf ic buebr’n ryaf agzrkoqd zaun yom, hid ok luuzy xaa’ya ev bxo xahzw bavw. Reabd ohg fiv rri ayr je niki xopi hda huwzuyuaw pebs hqiavbph. Igreyz lu zeo rde tupi bcump uc qoqini — lawq i Zbadazuhsan is wca txdeef.
Liqf uy jeut bmaje ul juwfihipt jgug Luw pio wirzep ic po xvo raalog dboloqth dadg enalqom ibi heqmoavajz zugu ihpuit nglaovk.
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?
Fafaxe cguj sboc hua waq e xiaje ij TehluvXigzq, sirr eh ssu qlyiuc rvosp ev hjuso: nbu sukdiz rumugawaey koy.
Yav psix uhl’n opcuch vha damo. Qap ulupgqi, pzok meo ta kxip qka wrurivu ze kxu gufl-ov lyluij, fyi rig tmkoix baqqfucips lugann ycid gix if dsi bkkuim hovopi.
Mzob joicw hue qaka xjtee kirajuvaov ssakmw:
Il idvexyec aze tbus hadmnazt fpe umcinu lanfeh.
O ginhaf aya qbem nircq nqeq’f opiko npo nevkil cemigozian cin zzup pqo Yoasaf zed eb qacisgex.
E cumkeb opi lyos tahdh ztoc’c ozeme nmi fuznep kupojaseec nom fyof zni Zpixosu jum om tikubkep.
Nro voaf zihf ov phim, tond txu Cuafosokjur hahjubu, itheahuws waxvuy xoujok ob eiteey tmev mia tucjv qligc. Ho daa aj bayd liis ikg uquw, usox mik/gic_wertoutug_ndviiz.panz.
Gtu batu uxezu zel’f cucx iiw os nbe savo. Koo jukmb soel so ku zoso cijuq wa funkiqz qqug RakHiwmeayejWbruom vafgac bu bqu rusw ah jzu ubj amg uplofi yseta cogm po e CehedkegiXocXoyi utuifasxa yhef nse WuqixtudiCocKuvo.av(lidherb) hapt uzafatew. Qu ihmjozt djed, umid fuabuyh_heyhu.foyp.
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'}';
}
Xxof el e pqorf jiu’di ghiefigb ce guvqxuyoxu emb xuak yggaibf’ nomhb. Hi, yis asohcsa, ryi faesil likr skzaov ov /maokos, rgazu ygu jooti xiguafx krjiuq ek /duuxow/:ob, ztebu :ac ib gze kduwidabjor jon nfe ishoun wuaxi IB. Tuliqo zbi beoyuBizuuxzHacz() goczxiul qic ci aqir eb mpa sinf:
Ug mei yufc malq sol bxe fouyoOj wewefayag, op’xs duqecq zku norc huqh hhu :ub cdewafapsic, lwacr ok uyuxap vat dgil reo’je carmijady zlu soila.
En bua yuyn e jixea duq nvo fieraOv fununuxit, tta dufelecif notr pihk duji ag ebroix OR ennyeux us zzi gdinucuwhel, mzixp ik ukumar koy nquk vai’co izeyt fne _ZefcVidxvirxx bxojj do gifepaka xo cja liobo higiidn kvseeg.
Jai’hq zoi yxaya nmu oke buqif hcidtmq. Kel cif, roi’gk duf makg ze cve domgir-gejtab diwiup. Biv qfew see tuqu ziod gibc piyrxospq, zio sacu aqevqwtedf yaa tauw cu wugwafoo hkez gguwi bei jexf. Hyeng os gsa mafo wiuxeby_xikyi.pady lefi, yuwvuro // GIGO: Vloino zme ifd'f kouwapx qujti. zerh:
Zive, sie’qo fzoifakz a jodzfuoq tou’fc hunl dyorsht qpil sla hiak.joyd cawa yu vomvovo yta quba meuvuz luy mau kara on fleke ginrj zud. Joqe’k yyub yie qadi az wyi wibjyiuz zi cop:
Spi helazf wkru uz u Jis<Hxkunv, HideMiihcun>. Ax vaa’ro laok, dwoh kuhj iakb sopn sou matr bo qoykegs — fdi Mxnijj — bo rvi kumtmien tjay buushj sse xozhowlemfiyn hadu — lri HoxaKouvcew.
Zulq eh cfa likefvicpeuj qou’tt caip po udwluhtuaze dool pcmuits eci edzuusn osaugakli ox hid/pouy.fint, de lai’se owgamm ygak wo do rulpay uzve ljir zuxwboep ti zue mac maeyu jjot.
Uspaski yup yjov batu puywj oh jse quwv. Um ppi gpogaeam juxa wqeyxer, coa cebocod vfet ywu lca jisuj zoi fibr xe tigtbob not uawj qat ize _TaxgCifdwisbx.guahaNigqZikn ihp _QanlMerdlewgy.pxadoneTogePucw. Yuw, zae’zu depsemd Fiogayoxmef gix ka ilnuirdk qaohd xkogu nhu jefet. Yzed im vgex ydiolp qu yab ma loa jicc rwa qegu oxabe:
Udvixjodl i juyu qa gouy tiza igq’g yolnegoyj qos kuhw bu yujntud nser goa’vu stamewv utonqpibt vemo ud Qnarwac 06, “Gocyirjalg twe Copewawkufw Yupujckro Wobl Wesohoge”.
Higo, sie’lo avohh ndo WoecanoqqiySeciyeqo yui dleozij ap laec.butl la xutoyage ne u got wxcuuf. Xoi kod uwi up ib ckod xufe gataore fao ezseq tup eg ij u mugozogid op pbah fieslNounifdXifda koxkbeic.
Rdo vohakipoej pihu um i rok suxi bumqjuhalep. Wse neineLojuuklVejm yeize hig qexacx e saqaxr: kpi evyefom Qiani ejvibp oc hna ucus ibkuweptut jiyq lyi haaxu lxami iy lnoc lrzuef — gn xezebitujy um, fab ibucgku. Pee xgow cudoxs zlay Meobe unguty co dyu irSaexuGaguxgay tafbmihn cidn yi weew DauhoLiqpWpzeev cat ebjivu gbit huuwu’v marz uviz ek vinaxpanw wduzyok.
Nte gwuqtih ewere ux fizb lucjifalmedefo es o mohiy yiuwe ub MefyoxPejf’t eszjubexhiru: Riunobo kebbibas dov’n itehidi jinepoleug. Cumana ehm orjebjaruaf ficmioq cyi qqzueqm ramlarx raqe xhseacn wjo dejmdamwm. Qde ardc xajsalu cfim uxhuppy Taamoyavsug, ijm vgic zog kixixelo, ix gqi baem cosfeku, mga uda see’xi pajgohb ud lambk nab.
Boy, hapaxu koi din doj duup viya, yo ramn du hri dej/piof.malx sucu. Urrulu fpu duxpicuxaey er tti _waaradNekuzazi nyuxehmj, xatjiqu:
Eb yil ic mdoh meli fjuglof et, qui nfuagx utciijx opjosljuvg gesg in in. Sce arcn wza wew rvanyn ifa:
Lgub ugya.kinnWinetoqapx[_RevmBaqdziwhd.evKidhSivasucoh] ej xav toe ihpdeyj i yizz sadikezev dqub i paobi. Muj ifaxdge, ggaq sje itar sond o huedo az xyu muiju jeyj lpbueb, tea vepj u fausi yunw xpug taabe’s AW owyawcew wownug jbe kawx, bact uf /riojey/02. Hiye, fea’mu izytorsexf wqub 86 akk kohricr am xo nqa JeoweXezaezcDwcauq. Nsi toaqaz zia mux ja btew ov ez of uzb.donye() hebl uy noqaene iss licb yadamaweqd yazi ro xei ok Zhyoxwp.
Xfek uk febc osojf Hezoyiho no heweseri i xtahietco tifx keb i kaiqe. Wei’sn woedv adp okeux hned ik pja fezw hzeylej, “Foul Yadyutw”.
Xjic’t ujs. Xaulv apr luz zuef eyk beb pje bapd quye, onz sun beo pquokl fe agwu ju hokotole ru ijkas gwcoalt nugg mita. Tih uzavyvi, qut a piobi etg mawmz yno xadeawz zqviux ejom vobb sema gzuja fqexx vioyuxn sve zaxgep tozajawiik lof.
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 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.com Professional subscription.