Why I Will Not Use Architecture Navigation Component

Discussing this topic recently with many people made me think: Is the problem AAC Navigation Component solves actually big enough and worth the effort to use the component and refactor? After diving into it and organising my thoughts while writing this post, the conclusion is clear: no.

Pic by Xevi Camacho

Each time new Architecture Component was presented, I felt excited and my thoughts were: “Finally there is a library to solve this!” However, after the Navigation Component presentation my thoughts were like: “Nah, I don’t have a problem with this, but maybe someone else does.” Now, after looking into the component, I finally formed my opinion: “Navigation Component would cause me more harm than good, let’s stick to In-App Deep Link Navigation.”

Do you know that feeling when you look at something and you don’t like it, but you cannot explain why? Navigation Component was exactly such case so let’s explain why.

Before We Dive Into What Isn’t Good

There are many things which are great about Navigation Component and especially the effort from Google of trying to make things easier for developers and give guidance and path to go. I would really like to appreciate the work of developers on this project and I believe things will get much better over time.

While saying that, there is too many showstoppers for me to even give the library a try within project. Also to be complete — I love ViewModel, Room and LiveData.

Navigation Component Has Its Flaws

These flaws are not critical and might be fine for you, but they are not for me. Many of these are not a problem, because they would be implemented bad way. They are simply a problem, because it couldn’t be implemented better with current requirements, design and tools.

Large API: Looking at the documentation, currently there are 5 interfaces, 29 public classes, huge blob of public methods, properties, plus its own XML specification and tooling.

We can say that we need much less to start, but only introduction article takes 20 minutes to read(Read-o-Meter) and mentions large part of public API. Very opinionated: Being opinionated in general is a good thing, however there seem to be too much — You must use Android Studio to generate XML with ids to navigate in code. You must use Fragments. You must use different Navigator classes. You should have single activity, you must put deep links in that XML, you should put animation and parameters there and more.

Putting many limitations may significantly reduce flexibility and makes incremental refactoring of existing projects more difficult. XML: File navigation.xml from Google Sample Project contains information about all screens, basically moving this away from AndroidManifest plus adds extra info about screen relations, deep links, animation and parameters. Even though you can use subgraphs and <include> clauses it might not scale well. Just imagine your most complex layouts with your Manifest combined. Doing too much: Back stack management; Changing fragments; Passing parameters; Handling deep links; Listing all screens; Animations; Click listeners; Menu listeners…

All of that is related to navigation so it is valid having it in a single library. There are specialised libraries for deep link navigation only, parameters, many for animations. This suggest that each of them might be a problem of itself and putting all together smoothly might be very hard to achieve. Android framework dependency: This might sound too pedantic. Anyway navigation could be considered as part of logic and this logic most probably belongs to ViewModels or other layers. There are good reasons why to keep these layers unaware of Android framework. Navigation Component makes this harder. Testing: There is testing package, but there is only single line comment to TestNavigator and no recommendations how to test. Looking into the code reveals you can do your assertions on public field mBackStack Unfortunately because of usage of Android framework related classes you can forget about this in unit tests without Robolectric. Permissions, Google Sign-In (startActivityForResult) : Sometimes you just have to switch out of Fragments and use Activity APIs. Having everything wrapped by Navigation Component, this might become weird as you have to jump out of the bubble of Navigation Component and then somehow jump back. Conditional deep linking: Documentation suggests implementing that logic on receiver of deep link, but what if we want to decide the destination based on deep link parameter or state(e.g. logged in/out). Using Navigation Component forces us to put this logic somewhere to screens. Breaks Instant Apps: Separation of Instant Apps is achieved through grouping Activities into modules. To be able to produce navigation graph, we have to have all fragments accessible within our class path, making it impossible to split the app into smaller chunks so the whole app has to be instant app. Silently breaks analytics: Firebase and GA screen engagement automatic tracking will stop working due to usage of fragments for navigation. Of course this is easy to fix, but it is yet another thing to do. When refactoring from previous code it may actually became complex while switching from Activity-oriented to Fragment-oriented navigation.

There are other things which might be problematic dependent on opinion, but I tried to list the main ones which attracted my attention.

Conclusion

Navigation Component might sound promising and will definitely evolve, but has its drawbacks and I was pretty surprised how many could came out of my mind while exploring it.

The question is if the problem to solve is big enough for the complexity and impact of the solution. So far it seems this is not the case at all.

Your project might have different requirements, so my suggestion would be not using Navigation Component just because it is recommended, but carefully evaluate benefits and price for you from using it.

Do you disagree or you are happy using it, please let me know in discussion.

Thanks for reading.