Fixed
Status Update
Comments
il...@google.com <il...@google.com> #2
Activity destinations should be considered exit points for your navigation graph - they are not part of the NavController's back stack and therefore not being sent to OnNavigatedListeners is working as intended.
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #3
Thank you for your explanation, but although that is the intended behavior, it is still confusing.
In my opinion, the developer expects to be notified when any navigation action defined in the graph is performed, regardless the destination.
Although that action is considered an exit point, it is an action defined within the graph and it is indeed a navigation action happening in that graph, so I don't understand why it is not notified to the "OnNavigated" listener when it has indeed navigated, regardless if it affects or not the back stack.
I that is the intended behaviour, then it should be rather called something like "NavController.OnBackStackChangedListener".
In my opinion, the developer expects to be notified when any navigation action defined in the graph is performed, regardless the destination.
Although that action is considered an exit point, it is an action defined within the graph and it is indeed a navigation action happening in that graph, so I don't understand why it is not notified to the "OnNavigated" listener when it has indeed navigated, regardless if it affects or not the back stack.
I that is the intended behaviour, then it should be rather called something like "NavController.OnBackStackChangedListener".
il...@google.com <il...@google.com> #4
Yeah, naming is hard :)
Right now, NavController.OnNavigatedListener gives you a NavDestination that always equals navController.getCurrentDestination(). It doesn't give you what action you triggered, arguments, or anything else (including operations that don't change getCurrentDestination(), such as singleTop actions or activity destinations), so I could definitely see this more as a OnDestinationChangedListener.
I'll reopen this to track renaming the listener to something more appropriate to what it actually is doing or updating the documentation to make its role more clear.
Right now, NavController.OnNavigatedListener gives you a NavDestination that always equals navController.getCurrentDestination(). It doesn't give you what action you triggered, arguments, or anything else (including operations that don't change getCurrentDestination(), such as singleTop actions or activity destinations), so I could definitely see this more as a OnDestinationChangedListener.
I'll reopen this to track renaming the listener to something more appropriate to what it actually is doing or updating the documentation to make its role more clear.
zv...@gmail.com <zv...@gmail.com> #5
Project: platform/frameworks/support
Branch: androidx-master-dev
commit fcc0c6059e31f7e53396db8cce0ac62d76a1c2d8
Author: Ian Lake <ilake@google.com>
Date: Fri Nov 30 13:14:58 2018
Rename OnNavigatedListener
The callback to onNavigated() is not only
called in result to a navigate() call, but
is actually called whenever any navigation
event happens, be it single top navigation
events or popBackStack events.
Therefore the name should reflect what is
actually happening.
Test: existing tests still pass
BUG: 118670572
Change-Id: Iad45d646e859428a4f744992821916906ca2d34f
M navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt
M navigation/runtime/api/1.0.0-alpha08.txt
M navigation/runtime/api/current.txt
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
M navigation/ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/ActionBarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/CollapsingToolbarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/NavigationUI.java
M navigation/ui/src/main/java/androidx/navigation/ui/ToolbarOnDestinationChangedListener.java
https://android-review.googlesource.com/838931
https://goto.google.com/android-sha1/fcc0c6059e31f7e53396db8cce0ac62d76a1c2d8
Branch: androidx-master-dev
commit fcc0c6059e31f7e53396db8cce0ac62d76a1c2d8
Author: Ian Lake <ilake@google.com>
Date: Fri Nov 30 13:14:58 2018
Rename OnNavigatedListener
The callback to onNavigated() is not only
called in result to a navigate() call, but
is actually called whenever any navigation
event happens, be it single top navigation
events or popBackStack events.
Therefore the name should reflect what is
actually happening.
Test: existing tests still pass
BUG: 118670572
Change-Id: Iad45d646e859428a4f744992821916906ca2d34f
M navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt
M navigation/runtime/api/1.0.0-alpha08.txt
M navigation/runtime/api/current.txt
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
M navigation/ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/ActionBarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/CollapsingToolbarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/NavigationUI.java
M navigation/ui/src/main/java/androidx/navigation/ui/ToolbarOnDestinationChangedListener.java
zv...@gmail.com <zv...@gmail.com> #6
Project: platform/frameworks/support
Branch: androidx-master-dev
commit 1a5551e0e3145b1e309577a1282d28fa1b14e956
Author: Ian Lake <ilake@google.com>
Date: Mon Dec 03 13:22:31 2018
Correct naming of add/removeOnDestinationChangedListener
Ensure that the add and remove methods
use the same naming convention as the
listener class itself
Test: ./gradlew bOS
BUG: 118670572
Change-Id: I71dd174f7abd3a870c12b26c0aef64ff1512ceea
M navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt
M navigation/runtime/api/1.0.0-alpha08.txt
M navigation/runtime/api/current.txt
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
M navigation/ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/CollapsingToolbarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/NavigationUI.java
M navigation/ui/src/main/java/androidx/navigation/ui/ToolbarOnDestinationChangedListener.java
https://android-review.googlesource.com/839441
https://goto.google.com/android-sha1/1a5551e0e3145b1e309577a1282d28fa1b14e956
Branch: androidx-master-dev
commit 1a5551e0e3145b1e309577a1282d28fa1b14e956
Author: Ian Lake <ilake@google.com>
Date: Mon Dec 03 13:22:31 2018
Correct naming of add/removeOnDestinationChangedListener
Ensure that the add and remove methods
use the same naming convention as the
listener class itself
Test: ./gradlew bOS
BUG: 118670572
Change-Id: I71dd174f7abd3a870c12b26c0aef64ff1512ceea
M navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt
M navigation/runtime/api/1.0.0-alpha08.txt
M navigation/runtime/api/current.txt
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
M navigation/ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/CollapsingToolbarOnDestinationChangedListener.java
M navigation/ui/src/main/java/androidx/navigation/ui/NavigationUI.java
M navigation/ui/src/main/java/androidx/navigation/ui/ToolbarOnDestinationChangedListener.java
il...@google.com <il...@google.com> #7
We've renamed the listener to OnDestinationChangedListener to make it more clear that it is only called when NavController's getCurrentDestination() or its arguments change, precluding activity destinations.
[Deleted User] <[Deleted User]> #8
i am facing null bundle exception while using nav graph arguments even i have set the default arguments in
nav graph and also check null in code
here is my sample code of Kotlin
private val args : BottomSheetCartFragmentArgs? by navArgs()
arg?.let {
product = it.product
isFromCart = it.isFromCart
screenName = it.screenName
}
Nav graph arguments
<argument
android:name="product"
app:argType="com.dawaai.dawaaidukaan.model.Product"
/>
<argument
android:name="isFromCart"
android:defaultValue="false"
app:argType="boolean"
/>
<argument
android:name="screenName"
app:argType="string"
android:defaultValue="recreate_order"/>
nav graph and also check null in code
here is my sample code of Kotlin
private val args : BottomSheetCartFragmentArgs? by navArgs()
arg?.let {
product = it.product
isFromCart = it.isFromCart
screenName = it.screenName
}
Nav graph arguments
<argument
android:name="product"
app:argType="com.dawaai.dawaaidukaan.model.Product"
/>
<argument
android:name="isFromCart"
android:defaultValue="false"
app:argType="boolean"
/>
<argument
android:name="screenName"
app:argType="string"
android:defaultValue="recreate_order"/>
jb...@google.com <jb...@google.com> #9
Re #8 - please file a new bug with a sample project that reproduces your issue.
cr...@gmail.com <cr...@gmail.com> #10
Hi I'm facing a similar issue.
My OrdersFragment has one nullable argument called Option:
<argument
android:name="option"
app:argType="string"
app:nullable="true" />
private val args : OrdersFragmentArgs? by navArgs()
And inside the onViewCreated of this fragment I have:
args?.let {
if(it.option.equals("Completada")){
getCompletedOrders()
}else if (it.option.equals("Cancelada")){
getCanceledOrders()
}
}
Then when I compile the app and I went to the ordesFragment the app got crash:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.elrestaurante, PID: 3388
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:581)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:54)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:35)
at com.example.elrestaurante.ui.orders.OrdersFragment.getArgs(OrdersFragment.kt:62)
at com.example.elrestaurante.ui.orders.OrdersFragment.onViewCreated(OrdersFragment.kt:83)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1814)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:538)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.IllegalArgumentException: Required argument "option" is missing and does not have an android:defaultValue
at com.example.elrestaurante.ui.orders.OrdersFragmentArgs.fromBundle(OrdersFragmentArgs.java:36)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:54)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:35)
at com.example.elrestaurante.ui.orders.OrdersFragment.getArgs(OrdersFragment.kt:62)
at com.example.elrestaurante.ui.orders.OrdersFragment.onViewCreated(OrdersFragment.kt:83)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1814)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:538)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
I/Process: Sending signal. PID: 3388 SIG: 9
My OrdersFragment has one nullable argument called Option:
<argument
android:name="option"
app:argType="string"
app:nullable="true" />
private val args : OrdersFragmentArgs? by navArgs()
And inside the onViewCreated of this fragment I have:
args?.let {
if(it.option.equals("Completada")){
getCompletedOrders()
}else if (it.option.equals("Cancelada")){
getCanceledOrders()
}
}
Then when I compile the app and I went to the ordesFragment the app got crash:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.elrestaurante, PID: 3388
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:581)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:54)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:35)
at com.example.elrestaurante.ui.orders.OrdersFragment.getArgs(OrdersFragment.kt:62)
at com.example.elrestaurante.ui.orders.OrdersFragment.onViewCreated(OrdersFragment.kt:83)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1814)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:538)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.IllegalArgumentException: Required argument "option" is missing and does not have an android:defaultValue
at com.example.elrestaurante.ui.orders.OrdersFragmentArgs.fromBundle(OrdersFragmentArgs.java:36)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:54)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:35)
at com.example.elrestaurante.ui.orders.OrdersFragment.getArgs(OrdersFragment.kt:62)
at com.example.elrestaurante.ui.orders.OrdersFragment.onViewCreated(OrdersFragment.kt:83)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1814)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:538)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
I/Process: Sending signal. PID: 3388 SIG: 9
Description
Version used: 1.0.0-rc02
When using a Fragment such as:
<fragment>
...
<argument
android:name="myArg"
app:argType="string"
app:nullable="true"
android:defaultValue="@null"/>
</fragment>
The defaultValue="@null" causes that attribute to be dropped by the NavInflater (due to now XmlPullParser works), meaning the resulting arguments Bundle can be null as there is no way to distinguish between no default value being set and a null default value being set.
Unfortunately, even in the case where no arguments are required, Safe Args' fromBundle() and, by extension, the by navArgs(), require a non-null Bundle.
fromBundle() should only throw on a null Bundle if there are required values.