Single Activity Architecture, will nav_graph getting so big? - android

i just learned about Single Activity Architecture with NavigationComponent.
And i just curious, will our nav_graph.xml get so big? because all of the destination/fragment is writen in that file

The main_graph can get bigger as destinations increase. What I usually do is create multiple navigation graphs and include them in my main_graph (nested nav-graphs) and write my final destinations in child graphs.

Related

Can a second navigation graph be used as a nested navigation graph?

The new android navigation component is what seems to be recommended. Im follow the official tutorial on graph nesting.
To group destinations into a nested graph, do the following:
In the Navigation Editor, press and hold the Shift key, and click on
the destinations you want to include in the nested graph. Right-click
to open the context menu, and select Move to Nested Graph > New Graph.
The destinations are enclosed in a nested graph. Figure 2 shows a
nested graph in the Navigation Editor:
Everything works well so far, I just have one issue.
The nested graphs are all part of one big xml file, this is an issue because it can lead to merge conflicts when using source control.
So my question is can we have this same functionality if we simply create two navigation graphs and include the new graph as a destination?
Will everything work as expected or would there be unintended consequences to doing this.
For example poping back to the root of navigation controller? I'm not very familiar with Android but my fear is that a new navigation controller is created and I cannot easily navigate when having two navigation graphs.
Nothing in the tutorial seems to mention this.
As per the Reference other navigation graphs with <include>:
While this is functionally the same as using a nested graph, include lets you use graphs from other project modules or from library projects
An <include> is expanded at runtime to function identically to a nested graph - there is no difference in what you can do regarding popping up to other destinations, etc.
However note that Safe Args does not work across separate navigation graph files (as you could include that graph in multiple other graphs, so there's no guarantee that anything outside of that file actually 'safely' exists), so you would need to confirm that any use of Safe Args is within a single file (using other mechanisms, such as manually navigating or navigating by deep link to navigate to graphs you know exist, but cannot be verified at compile time).

Having multiple fragments at one screen with Jetpack Navigation component

Two fragments
I'm using navigation component and trying to understand is it possible to have two or more opened fragments simultaneously like mail app (one fragment is a list of mails, another fragment is detailed mail view). It's desirable to have them inside another container parent fragment.
Yes, it's even recommended to design your app for multiple screen sizes. You can do so by creating alternative layouts, e.g:
res/layout/fragment_items.xml # Screens smaller than 600dp available width
res/layout-w600dp/fragment_items.xml # Screens 600dp wide and bigger
where layout-w600dp/fragment_items.xml includes both fragments. This way you keep the same navigation destination and don't need to complicate things with conditional navigation.
It's desirable to have them inside another container parent fragment.
Depends. If you are going to use your list-fragment on multiple places, yes, because it would reduce duplicate code. If not, or your list-fragment is going to be different on multiple screens (you might add or hide some buttons) you don't need the container; and can just modify the fragment_items.xml layout for different screen sizes.

Navigating between activities in different packages

What is the best way to implement bottom navigation between activities that reside in different packages ? Where the packages import one another in a top down fashion.
Setup
I have structured my project as a set of packages; Essentially split into the main app, a number of intermediate PACKAGEs and the final end package :
app - Provides the main application and serves as the projects build target. It contains a single activity, Main, providing the primary entry point for the application. The navigation graph simply maps the only fragment to the ACTIVITY's provided by each of the imported PACKAGE's.
PACKAGE - Provides a single activity, ACTIVITY, to manage a dedicated task. The navigation graph manages the relationships between the various fragments supporting the activity; Additionally it includes link to the Final activity imported from end.
end - Provides a single activity, Final, which each PACKAGE importing it uses as the terminating navigation link for their navigation graphs.
So each package contains a single activity, one or more fragments and a navigation graph that manages the routing between them and a node pointing to the activity in the next package in the order app.Main > PACKAGE.ACTIVITY > end.Final.
Navigation
Given this structure I want to add bottom navigation, |Main|...|Final|, to each activity ACTIVITY such that there is a link back to Main and another onward to Final. Linking forward to Final is easy enough as enough as it's already a target in each PACKAGEs navigation graph but I am uncertain on the best method for linking back to Main. Similarly I want to provide bottom navigation, |Main|ACTIVITY|...|, to Final such that the user go back to either the preceding ACTIVITY or Main.
Considerations
What is the best means of providing navigation targets to the activities in the parent packages ? To me the following seem viable
Cross import all of the packages within gradle. That is app imports each PACKAGE and end, every PACKAGE imports both app and end, and end imports each PACKAGE and app. This is not very DRY but it will make all activities universally accessible.
Pass Main as a list to ACTIVITY, adding it to the navigation menu programatically. Similarly pass Main and ACTIVITY as a list to Final. Here I'm not sure, given that activites have lifecycles, if I should pass the activity class or the instance thereof to the child activity ? The advantage here is that I can readily create the backstack if it's missing.
Interrogate the "Activity" back stack as it already details the route to both ACTIVITY (That is it contains Main) and Final (That is it contains Main and ACTIVITY). Here it becomes tricky to create the backstack after the fact.
Use deep linking ? (I'm still reading up on this)
Should one simply cross reference each activity setting parentAttribute under the <activity/> in each PACKAGES's manifest.xml to provide the necessary navigation targets ? Here I'm not sure how best to add this to the bottom navigation graph/menu ? Also it becomes necessary to programmatically set the parentAttrbiute depending upon the route taken to reach Final.
Depending on how access to the activities is provided in 1 I'm not sure what the best means is of making such target accessible ?
Can this be done within a navigation graph ? Can I programmatically add activities from a parent package to the navigation graph ? Can a Placeholder be used to reference such items ? Can a custom navigation destination can be written to represent such items.
Should one simply populate the menu provided to the navigation menu used by BottomNavigationView ? Can one do this and support targets provided by a navigation graph, that is can one overwrite both OnNavigationItemSelectedLsitener and use setupWithNavController together ?
Note : While I have seen some similar questions and answers I haven't seen any that deal with activities in separate packages.
I solved this problem by interrogating the package manager to determine the activities that are available within my application, under my package name.
Adding metadata to each activity, under the MANIFEST.xml, allowed me to filter the activities I wanted to reference. Adding android:label and android:icon attributes allowed me to provide labels and icons for the buttons in the navigation view and to display them upon the app bar. Furthermore I could create intents for each activity and set these upon the menu items (One of the android docs mentioned that any menuItem that is not handled directly will have its intent attribute invoked).
I wrapped all of this into an interface and can now tack that onto the activities I wish to navigate too outside of the navigation graphs supported by the navigation components.
Note : It's possible deep links serve this purpose but I haven't seena nice example just yet.

Android Architecture navigation Component with Bottom Navigation?

Now I am wondering which is the most proper way of implementation when want to combine BottomNavigation with the new Android Architecture Navigation Component?
For now found two approaches:
Single Navigation Graph which maintains all BottomNavigation items and which is shown here from Google Codelabs: https://codelabs.developers.google.com/codelabs/android-navigation/#1
Multiple Navigation Graphs where every BottomNavigation item has its own navigation graph which maintains only its behavior and backstack which i shown here: https://proandroiddev.com/mastering-the-bottom-navigation-with-the-new-navigation-architecture-component-cd6a71b266ae
My opinion is that the second one is more clear and understandable, but maybe you have another opinion.
Having separate backstacks or not is a decision based on user experience but if you do want multiple backstacks for bottomnavigation then follow the link for correct approach by androidx developers.
https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample
I think it depends with the number of nested fragments you will have per each navigation item. The fewer the fragments then i would use the first approach and the more the fragments then i would use the latter approach

How to Start Second Activity with Navigation in Jetpack

You know It's official now: Google officially recommends single activity app architecture. But there is a difficulty here. We have multiple activities. So when I want to implement Navigation with multiple activities, but I failed.
They said: In cases where multiple Activities share the same layout, the navigation graphs can be combined, replacing navigate calls to the activity destination to navigate calls directly between the two navigation graphs. in here
So I create this :
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:startDestination="#+id/nav_graph_firstActvity">
<activity
android:id="#+id/nav_graph_firstActvity"
android:name="io.androidedu.FirstActivity"
android:label="First Activity">
<action
android:id="#+id/nav_graph_actFirstActvity"
app:destination="#id/nav_graph_secondActvity" />
</activity>
<activity
android:id="#+id/nav_graph_secondActvity"
android:name="io.androidedu.SecondActivity"
android:label="Second Activity" />
After that i can not find any sample for multiple activities in here.
There is some sample like that :
Navigation.findNavController(view).navigate(R.id.nav_graph_actFirstActvity)
But findNavController() wait for a view, not an activity.
How can I solve this folks?
Navigation is meant to help the Navigation on Fragments, as they mention it in the note in blue here
Note: The Navigation Architecture Component is designed for apps that have one main activity with multiple fragment destinations. The main activity “hosts” the navigation graph. In an app with multiple activity destinations, each additional activity hosts its own navigation graph. Modifying an activity to host navigation is discussed later in this document.
So what you can do is to use an Activity as a destination in your nav_graph1.xml and that Activity(the destination) has to have its own nav_graph2.xml.
This way you keep using Navigation as a way to go through your app.
It's true the way the google documentation you mention when using multiple Activities that shares same layout, it is a bit confusing. But I think what they mean is that you can merge the Activity1 with Fragment1 (nav_graph1.xml) and Activity2 with Fragment2 (nav_graph2.xml), into Activity3 with (Fragment1 and Fragment2) since they share the same layout, and you can use nav_graph.xml pointing to nav_graph2.xml
Hope it helps
Update:
Navigation.findNavController(view).navigate(R.id.nav_graph_actFirstActvity)
The view can be any view that is inside the layout that contains the NavHostFragment. It will search for the corresponding nav_graph.xml that corresponds to that view or all its parents.
I found that using actions to navigate to an activity will give you the error:
IllegalArgumentException: navigation destination xxx is unknown to this NavController
You can use directions like this:
findNavController().navigate(directions)

Categories

Resources