Lukas is a product manager for Android developer frameworks and tools. He was previously product manager for Google Tag Manager. He has held roles as a software engineer, management consultant and program manager for an agricultural development non-profit.View the profile
Ian is a software engineer on the Android Toolkit team, working on Architecture Components and Fragments. Previously, Ian worked in Android Developer Relations at Google and, before that, built Android apps at Facebook and Phunware. Ian has a MS in Computer Science from University of Southern California and a BS in Computer Science and Physics from Montana State University.View the profile
Sergey is a software engineer working on the Android UI Toolkit team. His work focuses on Android Architecture Components. Prior to Google he worked at SPB Software. He earned his degree from Saint Petersburg State University.View the profile
About the talk
The Navigation Architecture Component provides a framework for building in-app navigation. This session will discuss how to use the Navigation Editor in Android Studio, XML or the Java API to define your navigation graph, and how that simplifies navigating around your app and handling deep linking.
Good morning. Thanks for getting up early to be here with us even despite the fact that some of our Thunder might have been stolen by the three or four presentations before this that demo the navigation editor. Luckily. We have time to go into a little bit more to tail then any of the previous presentation. So there's a lot of good material here. And I'm Lucas Frost master of architecture components and with me I have Ian and Sergei who built the navigation component and navigation if you think about it is a problem that pretty much every app on
Android has to solve. But until now we haven't really given you anything to do that with other than start activity, which for various reasons is not the best way to go about that. So if you think about your job and making Android development easier navigation was a common problem with no real solution. And that means that there's a lot of things that you have to solve on your own. And those range from how to commit fragment transactions, hopefully without throwing an exception. How to test the navigation is happening
correctly and that the right things are happening with navigation occurs. Are not people into the various voices in your app and how to keep that deep those deep link schemes up-to-date as your app navigational structure changes. Passing arguments from place to place again. We don't give you a type Safeway to do that today. How to make sure they're up in back take users to the right place is particularly in sort of more difficult situations like someone deep linking deep into your apps navigation hierarchy.
And so what this means it is by the time you finish solving these problems you typically don't wanted to directions. You've either written 60% of a navigation framework or you've got a lot of error-prone boilerplate everywhere navigation needs to happen in your app. You got a bunch of parallel lines of code solving these various problems and the whole structure is fairly brittle. and that's why we're so sorry and Individually, these problems are pretty tractable. But if you look at Denver Real World example, you can see that they can get pretty hairy. So say
that I have an item screen in my app and it's accessible via deep link. So far so good, but if someone had navigated to the screen via opening the app from the home screen, they would have a couple other screens on the back stock. And so hitting it up. We want them to take that not out of the app from the item screen. We want them to go to the category screen and then the home screen and that means that if someone deeply into the app, we need to synthesize the screens and add them to the UPS stock before showing the item screen and talking with
third-party developer or he told me it's when you're in the middle of writing the code to do this to synthesize he screams and add them to the up and back stock. But only on a deep link, that's when you start to feel like maybe you're solving a failure of the framework. So is this a help solve problems like that that we're launching navigation and what we're giving you is a visual tool that lets you edit the navigation grab your app, which is represented in XML. And that lets you to find a set of available navigation actions arguments can pass from place
to place things like visual Transitions and then a single navigate call activates all about it runtime. And so last but not least that means one thing you never have to worry about again is touching the fragment transaction with your bare hands. so what the navigation graph is essentially just a set of what are the possible destinations people can reach in my app and those usually correspond to screens but not always so you can have the navigation controller just
changing the contents of a smaller part of the screen. What is a set of navigation destinations in the actions that link them and the actions really represent how you can get from place to place? So to actually navigate from point A to point B in an you're just going to call the correct navigation action run time. So let's take a look at what this looks like. Emmett switched over to the demo Okay. So what we see here is a set of navigation destinations and these are fragment destinations. Although other options are possible
and the lines connecting them with the arrowheads are actions. And those actions actually generate methods you can call it runtime. This whole thing is backed by XML as you all know and love. And the XML and the navigation editor have the same set of capabilities so you can use either one. We're going to add a screened here and what you're seeing is a set of available activities and fragments in my app. Okay, so we just added an option for them to actually answer this question successfully and win the game.
So now we're going to add an action to navigate to that screen. Great, and that navigation action has a bunch of options you can set obviously we're going to talk about the those a little bit more. For now, we're going to do one thing. So we're going to say if they've gotten to this congratulations screen. That means the game is over. So hitting back shouldn't take him back into a game that no longer exist. So that means is we want to on that action say let's pop to the match screen. And that means I'm going to pop off everything on the back stack in between this
destination and the match screen. So when you use our gifts to the congratulations screen when they hit back, there's going to go straight to the match screen. So a lot of other options I can set but we'll talk about that for now. Let's go back and look at the congratulations screen again, one other thing to mention that the key thing that is set. Here is the fragment class and that's what's actually in fan. She added a run time. And we see layout previews here because layout the navigation editor knows what layout is associated with that
navigation graph and because it knows what layout is associated with that navigation graph. I can double click on that fragment destination to get here into the layout editor. Great and everything that I've just done here adding this new destination to the navigation graph an action changing with the pop behavior of that action is all the stuff. I can also do programmatically run time. So navigation editor XML or programmatic all work just fine. Great. Now I'm going to hand the soft again to walk you through this in more detail. So the first question I might come to mind as well. This
is a totally new way of kind of structuring the UI of a wrap and kind of brings up this question immediately like, okay. So what what does my activity actually meant to do Rite Aid sell every kind of app has a very different starting points from where you guys are right now or maybe as of two days ago on how you kind of structure. Do you lie of your app on some may be very activity heavy for a fragment heavy very much in a different system. I'm all those are certainly very valid places to be on but we're moving towards a model where the activity is more just an entry
point into your app rather than the activity being the owner of the content of your app. It's actually just what's going to store kind of that Global state. So the global navigation, so if your bottom nav navigation drawers, you're still using an action bar on those are the kind. Things that activities managed but it's delegates to what we call a now supposed for contents. So are nice super simple activity here. We have an action bar on the top bottom nav on the bottom and his big white box in the middle that's are now supposed. So in the world
of navigation when you navigate between different destinations in your app, we're actually doing is just replacing everything inside that box right so that you have some kind of that Global navigation outside and we have hooks that you can hook that up to stay in sync with the actual now supposed. What is a super simple version of this look like? Well, if you're using fragments for Destination, you want to use Arnav post fragments. So here we just have a activities out that is literally just SAR 1 fragment. So you do this by including the navigation
fragment dependency as you might expect if you're using a totally different kind of destination, it will probably also have a different kind of math post that you adhere whether it's the custom view or whatever other item that they need, but for now post a few convenience methods the ability to set what's navigation graph you're using in XML. You don't need to do anything programmatically to set it up. It'll just go to the start destination of your graph by default. And then for fragments we can actually hook this up to the system back button on so we offer a method to
do exactly that so you don't have to overwrite on back pressed specifically for navigation Humboldt kind of hook up all that stuff using the magic of fragment through this as default Maps host option. That means that our activity actually gets to be two lines of code. It would be two lines but it doesn't fit horizontally on a slide. But all we need to do is just inflator layout stuck on sent to you and then hook up the up button now, normally this is a large operation. But because you've told us about the structure of your
graph, what we can do is in this case for using a column extension message on activity. It'll just be a static method for Java users that allows us to find the navigation controller bypass again the ID and the states the idea of are navajos fragment and that just gives us access to navigate up and navigate up is going to do the right thing based on your navigation graph. You don't need to actually do a lot of extra work here by giving us your graph. We are able to do this for you. But for most apps just having a single thing
is not actually what you have. Maybe you have something a little bit more. So we've kind of set up a second dependency navigation, uy which is really just a set of static methods that connect your navigation component with some of the material design components some of these things like bottom nav and things like that that are very much in that kind of global navigation space. But of course, it's 2018. So so static methods into extension methods on the classes that they operate on. So this is really easy for Cortland users kind of
integrated trap and have navigation feel like it's just something that exists in all of the components that are out there. So what does this look like if we again kind of make our navigational right to be a little bit more complicated on the top and a lot of bother navigation View. And in this case, we still have the same kind of app menu that you had before on a bottom navigation view. But what we do to kind of hook those things up. It takes two parts one your menu here is actually going to be using the same IDs that
you've had on each destination to each destination as a unique ID and we can actually use those same ideas on your menu items. So I kind of build this implicit link of oh well if you click the home menu item you're going to go to the home destination of your app. So encode we're just going to set up our action bar using actual bar. And then we can do the same fine now controller to get our access to the nav controller object. And then we just have a common extension for activity that allows you to be safe now controller. And this
does quite a bit of magic, but what it's doing is actually going to be receiving events on when you've navigated in your nav controller and using the labels that you set up in your navigation graph to update the title of Your Action bar. And we also have another helper method if you're using a drawer layout to automatically change it from a hamburger button into a back arrow based on what destination you're on the really kind of just those helpful patterns to make sure that those things stay in sync. Similarly for the Bottom now it it's just you just call setup.
You call set up with nap controller and redo the two ways thinking here. So as you click on things in the bottom now, it'll change the graph as do the correct transition based on the material guidelines as well as as you navigate between your app. If you have separate button, it'll actually update the selected item in the bottom navigation. So this gives us a lot of power but not everyone is just using pre-built components that another team is provided. You have all your own custom UI. I thought that plane we really need to go deeper into what's now
controller actually gives you And for the super simple case, you have a button you wanted to go somewhere. We have a convenience method create navigate onclicklistener. You give it the ID of where you want to go what destination what action you want to trigger and will do all the work for you. Now. This is perhaps a little bit too magical so you can unroll it just a little bit and this case were using another extension method on view. So from any of you that's been created by now controller, you can actually get a
reference to your nav controller just by calling fine now controller as you might expect and use that nav controller to call navigate and just navigate to an ID of a destination or an action in your grasp. That's it. Like under the covers. This navigate is actually doing a lot of work. So the nav controller is talking to what we call a navigator XL for fragments. We're talkin to a fragment navigator that we provide. I'm at Navigator knows everything about oh, you called navigate. I know what fragment you're going to because you gave us your class name
and it's going to build all of the fragment transaction for you is going to call altabax back. It's going to do all the things you told us to do by putting that information in your navigation graft. So if you had pop up to its going to do all of that sort of stuff transitions, all of that is in this one line of code and all of it can be determined either programmatically we can add additional options to this method or something that you determine ahead of time as part of your navigation route. But for a lot of these things places, it's not actually just a
navigate but you have some information to pass to the next source. So for this you need to pass a bundle of information, so he ever passing a string and an inch and reusing are not helpful bundle of from an Android KTX. And it works it's fine. This is really useful for a lot of things. But the same point it's not very safe. If you doing this type here like what are you going to do? So we really want to make this a lot easier for guys going to talk about what we did here. Yeah rebuild something called Safety 1st grade
calculator by first of all, let's see what they're trying to resolve and let's go back to that requires us to fast screen name argument. And actually you can buy a category which has died and let's go back to the side and I replied to the made everything Court Oakland rape and screen and it has property property. The best friend name is it results in runtime exception and don't get the wrong. It's super easy to say but it's like I don't know. Okay. Now I
have this navigation all about that their destinations. So, let's see how it looks like an XML. as super simple Espanol And this allows us to be able to link that once you have an action that listed is fragment or a verb a action or activity we can check and make sure the best proper arguments. No, navigate to use this special object. instead of passing ID and a bundle of the same ID and same arguments Home Franklin directions glass is generated for you. It's just a fragment name + suffix directions
for every action Defiance have a destination. And those static methods make it pass required arguments with its makes us the best home argument there. And yeah later to set up yard and if everything is thyme safe and that is super simple really have is that the glass for our case is called fragment arts and all your are going to study to find types of matter. And from this small life Improvement we go to the bigger one, which is the place. Yes, so deep links
are traditionally something that Android has supported for the longest time so you can add intent filters to activities and no take over a web URL. I'm as well as like deep linking a super useful for notifications and things like that to link back into your out. But this gets a lot more complicated as you get a more complicated app, like how you structure these things and how you say like, all right. I need to build a notification. What is all of the code that's needed to actually get into the correct place in my app and pass the right kind of information here. So
for navigation rule really made deep linking kind of a First-Class citizen in our structure. So it's really two kinds of deep blink the explicit kind. So these are the things like for notification app shortcuts app widget and the new actions and slices things that are things that you create and are usually pending intent-based. These are all things that you're passing to another app or to the system to say, I want to go to the specific place in my app. The implicit side of things are more around the web
URLs and custom scheme you around Sousa be other apps triggering your house to Launch. And we handle both of these for navigation for explicit deep links. We have a specific classical navdeep link Builder and its sole goal in life is to deep link to a specific destination in your navigation graph by its ID, but it is going to do all of that work like it's easy to say but a little bit harder to actually make sure that all works in the system. But if we create a navdeep langfelder you crazy with the contacts you give it your graph
your destination and the arguments you have and then you can just call create plenty of work. We're doing all the work here to create the right synthetic back stack both within your grasp. And if you're using multiple activities your parents activities as well and we're going to pass that along and create the correct intense that gives you to the right place when you trigger this intense and then you just pass it through your notification. You don't actually To do more than this to get all the correct Behavior. For implicit deeplink.
These are again kind of links to web URL. Right? So in this case instead of it being something that you create programmatically it's information you include in your navigation grass. So here we are adding a deep link elements just like we out of the app arguments and actions to our grasp. These are just a deep length. And of course you can do all of this individual editor as part of the properties for a destination and it's really just as simple as an apple in your right and you're passing a you are right. Now. This is a sad if your eye but just boring and dumb and
know there's only so many apps that have just one year are they do so we have course support some wild cards. So if you want to do a. Star for a wild-card totally supported If you want to fill in the arguments for your destination, you can actually is Curly braces and wool pars the URL for you and extract those values and give them to you for your art so I can kind of in that same type safeguards now, you can get those directly from your drawer L and not have to reparse things. Like you already know what this is supposed to
be. Similarly, you can kind of combined the two if you want to make more complicated patterns. Totally can we also have support for auto verify if you're using app link to skip that disambiguation screen to make sure that you could do the same kind of thing if you're using navigation as well and you note here that we left off base t t p h d p s. So what we're doing here is actually doing both were saying HD to BHP s now I assume your servers are all HTTP, but you can't really control the your elves that others
are included. Maybe they accidentally took bath off of your your Elf on are we still want to support both of those who uses? It just is a convenience meth instead of having two lines that one. And of course that also works with custom schemes, so if you have your own scheme that you set up specifically for your app. You can also attach those two deep links. Now the best part is we've kind of worked across the tool spade. So besides just the navigation editor. It also works with the Manifest merger team. So you can add just a single navgrah
element to an activity in your manifest pointing to your graph and all of the deep links in that grass will then get expanded out to be the correct intent filter will build all those for you. And if you go to the Manifest merger view in Android Studio, you actually see if the exact line from your navigation file that generated content filter. So this means that we now have a single source of truth in your navigation graph. You know, this is not going to get out of sync with what you expect. It's not going to get out of
think as you change argument names in your XML file. All of this is kind of one since central place to do things that we think this is a lot easier. I'm for basically all of the implicit equal and kind of cases. Of course, we do do things, right. This is all action view URL as it would be for love you or else she can see it's at it directly to the line end. If you have multiple of them, it'll actually tell you exactly what line do you have multiple graphs associated with different activities. Those will all work just fine.
So what are the other subjects that is really important to all of architecture components is testing and testing of navigation is very hard and this is something that we're going to continue to look at over the alpha. Really want all of your feedback as well. But I wanted to kind of discuss what we think testing in a navigation World should look like So a lot of it is if all of the link between your destinations are through navigation, then it's a lot
easier to test a destination in isolation, right? You can test each destination by itself and then test just the outgoing edges or just the incoming arguments and not have to deal with. Oh did it actually do the right fragment transaction because we can test that just at the navigation controller level. Thought this is something that we are going to spend a lot more time on and in defragment talk yesterday and we actually talked about really trying to make fragments themselves much more testable be in isolation. So it's kind of a package
deal where we are trying to build testing into navigation controller to that also trying to build testable destinations as well. So you might be interested to do something right now. I'm so if you're out of espresso test and you want to test when I navigate to something doesn't go to the right place. Well, we actually have a add-on Navigator navigated listener. So you can actually hook it up to the nav controllers Navigator and get a call back of. Oh, did you go to the right place? When I click this button? This is one method
that we found pretty successful in kind of testing things completely black box outside of thing. Obviously, if you want to inject an app controller or use any other method, those are also perfectly valid ways of kind of setting things up. So what can you play with today? And what can you play with a two days must have looked at it? Right? So it is right now 1.00 Alpha zero one giving ourselves a long Runway of bug fixes and improvements here and it really comes down to two main artifacts the navigation fragments which includes the navigation runtime dependency
as a transitive dependency and also the Outpost fragments and a fragment navigator that you need to use fragment destination. As well as the navigation UI dependency which has those static methods and for every one of the dependencies for navigation. We have a dash KTX version of them if you're using Colin, so we really tried to make hollandaise first class citizen in the navigation World, especially for some of the things like if you are doing programmatic Construction, Visalia reading your whole navigation graph from a server on we have a kotlin DSL
as part of our calling extensions to make that a lot easier if you're using calling So there is more to do and I have Lucas talked about kind of where we going. You are going to need Android Studio 3.2 preview Canary 14 fuses and please do download it and try it out as a lot of great stuff there. So this is obviously going to become a really cool part of not just architecture components but jetpack overall. So with jetpack, we're going to take the same approach. We
took it architecture components. I just ordered blank sheet of paper. What do we want the Android developer experience to be and apply that much more broadly and navigation will be eventually part of the default experience. So when we get to stable then you know creating a new project in Android Studio is going to buy default start you up in the nap editor and should be a pretty great world. Njpac is available for you to try right now. It's right now. It's sort of got a much nicer
introduction to what all the key pieces of Android development are so too much easier on ramp and we're looking forward to expanding the story over time. There are more talks for you to go to a lot more detail on Android KTX and paging paging in particular is a really cool deep library that does a lot for you by tying together different pieces of architecture components in Jetpack. So I encourage you if you ever have a list of you with more stuff than you can hold in memory at any given time.
You really want to go to this page and talk. And we want your feedback. We want your feedback on the session first of all, but more importantly we want your feedback on the navigation component. The reason that we're launching to Alpha is not because we think that this is sort of you know, really untested and untried we've actually done a lot of pre-release testing of this but we want to get to Alpha because we want to get a lot of feedback from the community on it before we lock down API and switch over to Beta so this is a great time for you to try it out.
Tell us what works for you tell us what doesn't and, you know, either communicate directly or on a public issue tracker. We would love to hear from you. You're a feedback has been really critical in every point of this journey and making sure that were attacking the right problems with the right Solutions. So, please do try it out and tell us what you think. And thank you.
Buy this talk
Access to all the recordings of the event
Buy this video
With ConferenceCast.tv, you get access to our library of the world's best conference talks.