Status Update
Comments
il...@google.com <il...@google.com> #2
Oh I forgot to mention that I thought it might be connected to this issue:
ne...@gmail.com <ne...@gmail.com> #3
Please provide a minimal sample project along with the minimal steps to recreate the issue in the project.
ma...@gmail.com <ma...@gmail.com> #4
Sorry for the delay. I got a working example here:
I poked into it a little bit and it seems to be connected to
Steps to reproduce:
- Navigate from Second Fragment to Child nav graph (with non-nullable parameters).
- Navigate to Third fragment using SafeArgs and the app crashes.
Crash log:
Process: cz.dels.issues, PID: 1743
java.lang.NullPointerException: null cannot be cast to non-null type kotlin.Long
at androidx.navigation.NavType$Companion$LongType$1.get(NavType.kt:352)
at androidx.navigation.NavType$Companion$LongType$1.get(NavType.kt:342)
at androidx.navigation.NavArgument.verify(NavArgument.kt:76)
at androidx.navigation.NavDestination.addInDefaultArgs(NavDestination.kt:502)
at androidx.navigation.NavController.addEntryToBackStack(NavController.kt:1865)
at androidx.navigation.NavController.addEntryToBackStack$default(NavController.kt:1813)
at androidx.navigation.NavController$navigate$4.invoke(NavController.kt:1721)
at androidx.navigation.NavController$navigate$4.invoke(NavController.kt:1719)
at androidx.navigation.NavController$NavControllerNavigatorState.push(NavController.kt:287)
at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.kt:246)
at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.kt:162)
at androidx.navigation.NavController.navigateInternal(NavController.kt:260)
at androidx.navigation.NavController.navigate(NavController.kt:1719)
at androidx.navigation.NavController.navigate(NavController.kt:1545)
at androidx.navigation.NavController.navigate(NavController.kt:1472)
at androidx.navigation.NavController.navigate(NavController.kt:1930)
at cz.dels.issues.SecondFragment.onViewCreated$lambda-0(SecondFragment.kt:38)
at cz.dels.issues.SecondFragment.$r8$lambda$XDYnOS_cYrafiNQ5rcCu1WCn0IE(Unknown Source:0)
at cz.dels.issues.SecondFragment$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
Note: If in step 2 SaveArgs is not used then navigation works correctly. More information is here:
il...@google.com <il...@google.com>
mi...@gmail.com <mi...@gmail.com> #5
Ups a typo: Navigate from Second First Fragment to Child nav graph (with non-nullable parameters).
Note: sorry for the spam but I am not able to edit my own comment.
jo...@gmail.com <jo...@gmail.com> #6
This has been fixed and will be available in navigation 2.6.0-alpha08
il...@google.com <il...@google.com> #7
Branch: androidx-main
commit 6b358154b794a0456b089ac8e548bfb830dd6c22
Author: Clara Fok <clarafok@google.com>
Date: Tue Mar 14 17:56:12 2023
Fix missing non-nullable arg when rebuilding hierarchy
When navigating with NavDirections, args is populated with an empty bundle. This causes issue when we rebuild parent hierarchy while adding a new entry to NavBackStack. If the Entry being rebuilt contains a non-nullalbe arg, i.e. Long, this empty bundle will cause an exception.
Test: ./gradlew navigation:navigation-runtime:cC
Bug: 249988437
Change-Id: I5c8ce739ad9a3428c8a8de13eae391bfff0db5df
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
da...@gmail.com <da...@gmail.com> #8
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.navigation:navigation-runtime:2.6.0-alpha08
il...@google.com <il...@google.com> #9
da...@gmail.com <da...@gmail.com> #10
my intent was to see if you were interested and maybe try to do it myself and make a merge request. (I've read you don't accept merge request on
If you have a better idea for an API I'd love to know what is it
il...@google.com <il...@google.com> #11
1) Having a Fragment destination receive results from another Activity
2) Having a Fragment destination receive results from another Fragment
3) Having a custom destination receive results from either an Activity
4) Having a custom destination receive results from another destination
While 1) and 2) are possible through existing (not so great) APIs, Navigation operates on the level of 3) and 4) and would need to solve those problems before adding an API to Navigation that we're happy to support longer term.
We're tackling the core problem of 3) as part of a larger effort (see initial steps in
da...@gmail.com <da...@gmail.com> #12
makes sense.
Hope this will also outsource binding services and requesting permissions.
ar...@gmail.com <ar...@gmail.com> #13
ko...@gmail.com <ko...@gmail.com> #14
re...@infinum.com <re...@infinum.com> #16
Thank you in advance and good work so far on the navigation component!
ko...@gmail.com <ko...@gmail.com> #17
Is this feature to be released in near future?
am...@gmail.com <am...@gmail.com> #18
[Deleted User] <[Deleted User]> #19
ar...@gmail.com <ar...@gmail.com> #20
si...@gmail.com <si...@gmail.com> #21
il...@google.com <il...@google.com>
ke...@map72.com <ke...@map72.com> #22
ca...@gmail.com <ca...@gmail.com> #23
ke...@gmail.com <ke...@gmail.com> #24
[Deleted User] <[Deleted User]> #25
ng...@gmail.com <ng...@gmail.com> #26
ta...@gmail.com <ta...@gmail.com> #27
mo...@gmail.com <mo...@gmail.com> #28
ca...@gmail.com <ca...@gmail.com> #29
ke...@map72.com <ke...@map72.com> #30
il...@google.com <il...@google.com> #31
is...@gmail.com <is...@gmail.com> #32
am...@gmail.com <am...@gmail.com> #33
SharedViewModel fits well in cases where you have a known Subflow where each internal Fragment of this Subflow share/know about the same Subflow Logic and they know about each other.
However, when you want to trespass Subflow boundaries, lets say Subflow_1 launches Subflow_2 and expect a result back. Creating a SharedViewModel for this will pollute the code with a SharedViewModel per Subflow pair. Understand a Subflow could be a single Fragment, for instance a dialog that collects some User data and returns a result to whomever launched it.
Having a feature like this would be great. People including me will clean our code full of workarounds to achieve this.
What I currently do, I have an Activity scoped ViewModel shared by all the Fragments. This ViewModel I named MailBoxStore, that has internally MailBoxes. Each MailBox has the FragmentID it corresponds to. Actually each Fragment has 2 MailBoxes, one for Results and one for Inputs.
Every time a fragment is started after a navigation move, it ask the MailBoxStore if someone sent him either an Input or a Result. Depending on the type of message sent it will call then two methods like onStartWithInput or onFragmentResult.
I really would love a feature like this built in.
Also if the result could be an instance reference and not a Serializable Bundle, it would be much better!
Thanks
li...@booking.com <li...@booking.com> #34
vi...@gmail.com <vi...@gmail.com> #35
b9...@gmail.com <b9...@gmail.com> #36
[Deleted User] <[Deleted User]> #37
ra...@gmail.com <ra...@gmail.com> #38
mo...@tikalk.com <mo...@tikalk.com> #39
ka...@gmail.com <ka...@gmail.com> #40
al...@gmail.com <al...@gmail.com> #41
te...@gmail.com <te...@gmail.com> #42
mo...@gmail.com <mo...@gmail.com> #43
he...@gmail.com <he...@gmail.com> #44
as...@gmail.com <as...@gmail.com> #45
ca...@gmail.com <ca...@gmail.com> #46
ka...@gmail.com <ka...@gmail.com> #47
As for BottomNavigationView - you can make it work by using code from the sample project provided by the team.
Also there's no need to be rude to the team or express your frustration to everyone who starred the issue.
ca...@gmail.com <ca...@gmail.com> #48
So lets start again, the "work around" u mention about DialogFragment does not appear on any docs only the sharedViewModel "work around" if u can call it as that, second the "work arround" for bottomNavigationView has a lots of problems, the back navigation is not working as expected and also has a lots of open issues and nobody from google is answering to those..
ca...@gmail.com <ca...@gmail.com> #49
vi...@gmail.com <vi...@gmail.com> #50
ri...@gmail.com <ri...@gmail.com> #51
ap...@google.com <ap...@google.com> #52
Branch: androidx-master-dev
commit e493164e9a9ca69485b2642580134417b7d20aab
Author: Jeremy Woods <jbwoods@google.com>
Date: Mon Feb 10 01:44:58 2020
Provide getSavedStateHandle() on NavBackStackEntry
Added an API to allow users to retrieve a SavedStateHandle from a
NavBackStackEntry. Using the SavedStateHandle, users can store
Parcelable and Serializable objects on the NavBackStackEntry that will
persist over process death.
Test: Added NavBackStackEntryTest tests
Bug: 79672220
Change-Id: I81bb4b11581d2f6ac43afab5aa29a888f38286c0
M navigation/navigation-runtime/api/2.3.0-alpha02.txt
M navigation/navigation-runtime/api/current.txt
M navigation/navigation-runtime/api/public_plus_experimental_2.3.0-alpha02.txt
M navigation/navigation-runtime/api/public_plus_experimental_current.txt
M navigation/navigation-runtime/api/restricted_2.3.0-alpha02.txt
M navigation/navigation-runtime/api/restricted_current.txt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
ap...@google.com <ap...@google.com> #53
Branch: androidx-master-dev
commit 9e9ad24016a882826334b9793af9006d06fb8a30
Author: Jeremy Woods <jbwoods@google.com>
Date: Fri Feb 07 14:40:33 2020
Add getPreviousBackStackEntry() to NavController
Added a method that allows users to get the previous visible
NavBackStackEntry. (This means that it will not return NavGraphs)
Test: Added NavControllerTest
Bug: 79672220
Change-Id: I9486f8e3344bbce477a64b42adc933552c7f2c79
M navigation/navigation-runtime/api/2.3.0-alpha02.txt
M navigation/navigation-runtime/api/current.txt
M navigation/navigation-runtime/api/public_plus_experimental_2.3.0-alpha02.txt
M navigation/navigation-runtime/api/public_plus_experimental_current.txt
M navigation/navigation-runtime/api/restricted_2.3.0-alpha02.txt
M navigation/navigation-runtime/api/restricted_current.txt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
ap...@google.com <ap...@google.com> #54
Branch: androidx-master-dev
commit 316d65d9645ba5eff8146e23616c09288a603419
Author: Jeremy Woods <jbwoods@google.com>
Date: Fri Feb 07 14:39:01 2020
Add getCurrentBackStackEntry to NavController
Adding a convenience method to allow users to get the topmost
NavBackStackEntry instead of using getBackStackEntry() and
getCurrentDestination().
Also rewrote getCurrentDestination to use the new
getCurrentBackStackEntry.
Test: Added NavControllerTest
Bug: 79672220
Change-Id: I1477150b586fd8d26a63b99dc03cd839442e775c
M navigation/navigation-runtime/api/2.3.0-alpha02.txt
M navigation/navigation-runtime/api/current.txt
M navigation/navigation-runtime/api/public_plus_experimental_2.3.0-alpha02.txt
M navigation/navigation-runtime/api/public_plus_experimental_current.txt
M navigation/navigation-runtime/api/restricted_2.3.0-alpha02.txt
M navigation/navigation-runtime/api/restricted_current.txt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
jb...@google.com <jb...@google.com> #55
This has been fixed internally and will be available in the Navigation 2.3.0-alpha02 release.
With this change, you can now get a
If Fragment A
needs a result from Fragment B
..
A
should get the savedStateHandle from the currentBackStackEntry, call getLiveData providing a key and observe the result.
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Type>("key")?.observe(
viewLifecycleOwner) {result ->
// Do something with the result.
}
B
should get the savedStateHandle from the previousBackStackEntry, and set the result with the same key as the LiveData in A
findNavController().previousBackStackEntry?.savedStateHandle?.set("key", result)
Because this uses SavedStateHandle, all results need to be types that can be added to a Bundle (i.e
ia...@gmail.com <ia...@gmail.com> #56
How do I
[Deleted User] <[Deleted User]> #57
For your use case it's much more appropriate to use navGraphScoped ViewModel which would be common and shared among all A, B, C:
Or just pass it back through B...
mo...@gmail.com <mo...@gmail.com> #58
il...@google.com <il...@google.com> #59
Re #58 - the
If you’d only like to handle a result only once, you must call
on the remove()
SavedStateHandle
to clear the result. If you do not remove the result, theLiveData
will continue to return the last result to any newObserver
instances.
The result is scoped to the NavBackStackEntry
you access and will otherwise live as long as that destination is on the back stack.
[Deleted User] <[Deleted User]> #60
My "previous" Fragment has a ViewModel with SavedState handle, and right now I have to forward Fragments' SavedState handle into the ViewModel even though the ViewModel has it's own SavedState handle...
Or am I missing something? How can I reference ViewModel of the previousBackStackEntry and its' SavedStateHandle?
il...@google.com <il...@google.com> #61
Re #60 - there's two separate things to keep in mind:
-
previousBackStackEntry
is not tied to your Fragment at all, it is agnostic to what type of destination you are using (it would equally well if you were using Views or Composables for your destinations). It therefore provides no way to access anything related to your Fragment. This is intentional. -
A
NavBackStackEntry
(such as the one returned bypreviousBackSTackEntry
) is aViewModelStoreOwner
and therefore can be used to store any ViewModels you want viaby navGraphViewModels(R.id.your_previous_id)
orby viewModels({ findNavController().previousBackStackEntry!!})
. TheSavedStateHandle
we provide is just a shorthand for creating a ViewModel in theNavBackStackEntry
and getting itsSavedStateHandle
.
re...@lunabee.com <re...@lunabee.com> #62
Re #57
You could theoretically instead "previousBackStackEntry" use "getBackStackEntry(int destinationId)" and get its' savedStateHandle.. But it would be a very bad practice to hardcode a fragment to return it's result 2 steps back..
For your use case it's much more appropriate to use navGraphScoped ViewModel which would be common and shared among all A, B, C:https://developer.android.com/reference/kotlin/androidx/navigation/package-summary#navgraphviewmodels .
Or just pass it back through B...
What if I want to reuse fragments B&C in another nested graph so I don't want to hardcode the nav graph id in navGraphScoped? The only solution I found is to pass the graph id trough fragment args.
il...@google.com <il...@google.com> #63
Re #62 - that's certainly a valid option if you want to deliver results to a specific destination on your back stack. previousBackStackEntry
is just a helper for the most common case, nothing more.
[Deleted User] <[Deleted User]> #64
il...@google.com <il...@google.com> #66
Re #65 - yes, you can use the new Fragment Result APIs between Fragments when using the Navigation Component. Note that much of the
ja...@gmail.com <ja...@gmail.com> #67
hi. i found some issues with this
1) in code example..you have 'findNavController()' inside fragment 'onCreate'. When you rotate device app crash due to 'findNavController()' call. I found that when i rotate device then fragment (onCreate) is 'called' first and after that is called 'activity' (onCreate). I think that this is reason why navController is not available and throws this exception: 'Caused by: java.lang.IllegalStateException: NavController is not available before onCreate()'.
2) when i put code inside 'onViewCreated' then 'result' from dialog fragment is correctly propagated into 'previous fragment' but when i rotate device when dialog is shown and then i set 'result' and dialog is closed, no 'result' is received on 'previous fragment'. I guess its because
navBackStackEntry.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) // This event is never 'ON_RESUME' when fragment was recreated in time when dialog was shown
I also tried 'findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(viewLifecycleOwner) { //action }' but when device is rotated when 'dialog fragment' is shown, then this live data is not called (otherwise its called fine)
Please can you check this and show us some example how to handle 'dialog fragment' results in previous fragment even when you rotate device when dialog is shown? You can reproduce this issues very easily.
Just small suggested improvement 'navController.currentBackStackEntry!!' -> navController.requireCurrentBackStackEntry()
il...@google.com <il...@google.com> #68
Re #67 - please see
b9...@gmail.com <b9...@gmail.com> #69
#68 Is that link require googler account?
il...@google.com <il...@google.com> #70
il...@google.com <il...@google.com> #71
Well, apparently I can't paste links correctly today. It's
br...@gmail.com <br...@gmail.com> #72
lb...@gmail.com <lb...@gmail.com> #73
We have registerForActivityResult for Activity which is much nicer.
Why can't we have something like that?
Even the startActivityForResult is easier and shorter to remember than this...
And it's not even clear on
Description
screen that then returns the result to its previous screen).
Is that something planned? How is it expected to create flows like this with current version?