Navigating in Compose: Standards


Navigating in Compose: Standards

Navigating between screens is a standard act in an Android app… although, as
Zach Klippenstein famous,
“display screen” is a considerably amorphous time period. Naturally, we would like to have the ability to navigate
to totally different “screens” when these screens are carried out as composables.

How we do this can be a extremely contentious subject.

Roughly talking, there appears to be 4 main classes of options:

  • Use the official Jetpack Navigation for Compose

  • Use some form of wrapper or helper round Navigation for Compose —
    Rafael Costa’s compose-destinations library
    is an instance

  • Use Jetpack Navigation, however use the “basic” implementation as an alternative of Navigation
    for Compose, utilizing fragments to wrap your screen-level composables

  • Use some separate navigation implementation, equivalent to Adriel Café’s Voyager library

I can’t let you know what to make use of. I can let you know that you need to provide you with a set
of standards for judging varied navigation options. Primarily based on a survey of a bunch
of navigation options, listed here are some standards that you could be wish to contemplate.

Desk Stakes

In case your navigation resolution doesn’t help ahead navigation to N locations,
or if it doesn’t help again stacks (e.g., a goBack() operate to pop a vacation spot
off the stack and return to the place you had been earlier than), use one thing else.

Compile-Time Sort Security

One key level of utilizing Kotlin, and Java earlier than it, is kind security. The extra kind
security we get, the extra doubtless it’s that we’ll uncover issues at compile-time,
moderately than solely through testing or by the app going 💥 in your customers.

…For Routes/Locations

Whenever you inform the navigation resolution the place to navigate to in ahead navigation,
it’s possible you’ll wish to want options the place the identifier is one thing that’s kind protected.
Some options use strings or integers to determine routes or locations. That makes
it very straightforward to do some actually scary issues, like compute a vacation spot utilizing math.
Typically, primitives-as-identifiers supply little compile-time safety. You would possibly want
options that use enums, sealed class, marker interfaces, or different issues that
determine what are and usually are not legitimate choices.

(and in case you are asking your self “what about deeplinks?”, that’s coated a bit later)

…For Arguments

Continuously, our screens want information, whether or not an identifier (e.g., major key) or
the precise information itself. So, we would like to have the ability to move that information from earlier
screens. All else being equal, you would possibly wish to want options that supply compile-time
kind security, so you don’t wind up in instances the place you present a string and the recipient
is anticipating an Int as an alternative.

A associated standards is “content material security”. You would possibly wish to want options the place your
code can simply move the info, with out having to fret about whether or not it complies with
any solution-specific limitations. For instance, if the answer requires you to URL-encode
strings to have the ability to move them safely, that isn’t nice, as you’ll neglect to do that from
time to time. Ideally, the answer handles these types of issues for you.

…For Return Values

A minimum of for modal locations, equivalent to dialogs, we regularly must move again some
form of “end result”. For instance, we show a dialog to permit the consumer to choose one thing,
and we want the earlier display screen to seek out out what the consumer chosen. Generally, there
are methods of carrying out this outdoors of a navigation resolution, such because the dialog
updating some shared information illustration (e.g., shared Jetpack ViewModel) the place
the earlier display screen finds out about outcomes reactively. However, if the navigation resolution
you’re contemplating affords return values, and you propose to make use of them, you may want
to want ones the place these return values are additionally type-safe and content-safe.

IOW, forward-navigation arguments shouldn’t get all the security love.

Help for Configuration Change and Course of Dying

Prefer it or not, configuration adjustments are actual. Birds, maybe not.

A method or one other, your app wants to have the ability to deal with configuration adjustments,
and your navigation resolution ought to have the ability cope as effectively, to help your app.
This contains each retaining the navigation information itself throughout configuration adjustments
and, ideally, having a sample for app information in your screens to outlive as effectively
(e.g., Navigation for Compose’s per-route ViewModel help).

Associated is course of demise:

  • The consumer makes use of your app for some time

  • The consumer will get distracted by some not-a-bird for some time, and your app’s UI strikes to the background

  • Whereas within the background, Android terminates your course of to release system RAM

  • The consumer returns to your app after your course of dies, however inside an affordable time period
    (final I knew, the restrict was half-hour, although that worth might have modified over time)

Android goes to wish to not solely carry up your app, however faux that your course of
had been round all that point. That’s the place “saved occasion state” comes into play,
and ideally your navigation resolution advertises help for this, so your back-stack
and so forth get restored alongside along with your UI.

Hooks For Stuff You Would possibly Use

Solely you recognize what your app goes to want to do when it comes to its UI. Or maybe
your designers know, or your product managers. Or, hey, possibly you’re simply spraying
pixels round like Jackson Pollock sprayed paint.
Who am I to guage?

Regardless, there could also be some issues that you really want in your app’s UI or movement that
tie into what you will have out of your navigation resolution.

Many apps use these types of UI constructs. It will not be important that they be dealt with
through a navigation resolution — you would possibly have the ability to mannequin them as being “inside implementation”
of a display screen, for instance. However, it might be good to get a way of what patterns
are established, if any, for a specific navigation resolution to tie into these
sorts of UI constructs. For instance, if it is advisable to capable of not solely navigate to a display screen, however
to a specific tab or web page inside that display screen, it might be good if the navigation
resolution supported that. Maybe not important, however good.

And, for a few of these UI constructs, you is likely to be looking for to have a number of again stacks. For instance,
you would possibly wish to have it in order that again navigation inside a tab takes you to earlier content material
inside that tab, moderately than going again to different tabs that the consumer beforehand visited.
Help for a number of again stacks appears to be a little bit of a sophisticated characteristic, so if this
is necessary to you, see what candidate navigation options supply.

Deeplinks are well-liked. Right here, by “deeplink”, I not solely imply conditions the place a vacation spot
is triggered from outdoors of the app, equivalent to from a hyperlink on a Internet web page. I additionally imply
instances the place a vacation spot is decided at runtime based mostly on information from an out of doors
supply, equivalent to a server-driven “tip of the day” card that steers customers to particular
screens inside the app.

Should you assume that you’ll want such issues, will probably be useful in case your navigation
resolution helps them straight. That help will not be required — simply as your
different app code can navigate to locations, your “oh, hey, I bought a deeplink” code
can navigate to locations. Nonetheless, a navigation resolution might simplify that,
significantly for instances the place the deeplink is from outdoors of the app and also you want
to determine what to do with the already-running app and its present again stack.

When evaluating deeplink help, one standards that I’ll strongly recommend is:
deeplinks ought to be opt-in. Not each display screen in your app ought to be straight
reachable by some outdoors celebration simply by being tied into some navigation system
— that may result in some safety issues.

Additionally, contemplate how information within the deeplink will get mapped to your arguments (a minimum of
for routes that take arguments). Some navigation options will attempt to deal with
that routinely for you, however be cautious of options that use deeplinks as an excuse
to be weak on kind security. Ideally, there ought to be an unambiguous method to convert items
of a deeplink (e.g., path segments, question parameters) to navigation arguments, however
in a means that limits any “stringly typed” logic to deeplinks themselves and doesn’t
break kind security elsewhere.

Transitions

Your designers would possibly name for a particular method to transition from display screen X to display screen
Y, equivalent to a slide, a fade, a slide-and-fade, a fireworks-style explosion destroying
X with Y showing behind it, and many others. Ideally, the navigation resolution would deal with
these types of transitions, significantly if it is advisable to management the back-navigation
transition as effectively (e.g., the exploded fireworks one way or the other reassembling themselves right into a display screen,
as a result of that appears like enjoyable).

Growth Issues

Does the library have clear documentation? Does it appear to be maintained? Does it
have a transparent means of getting help? Does it have a license that’s appropriate with
your challenge? These are all frequent standards for any library, and navigation options
aren’t any exception.

Past that, navigation options have a couple of particular issues that you simply would possibly wish to
contemplate, equivalent to:

  • How simply are you able to help navigation the place the locations would possibly reside in several
    modules? Notably for tasks that go together with a “characteristic module” growth mannequin,
    it’s doubtless that you simply want a display screen in module A to have the ability to navigate to a display screen in
    module B.

  • Are there clear patterns for utilizing @Preview? In precept, a navigation resolution
    shouldn’t get in the best way of utilizing @Preview for screen-level composables, however it might
    be painful if it did.

  • Does the answer work for growth targets past Android? Maybe you aren’t
    planning on Compose for Desktop or Compose for Internet or
    Compose for iOS or
    Compose for Consoles. If you’re, you
    are going to wish to contemplate if and the way navigation ties into your Kotlin/Multiplatform
    ambitions.


This isn’t a whole checklist — if there are issues that you simply assume are pretty well-liked
that I missed, attain out!