Status Update
Comments
il...@google.com <il...@google.com> #2
ur...@gmail.com <ur...@gmail.com> #3
lo...@gmail.com <lo...@gmail.com> #4
an...@zappos.com <an...@zappos.com> #5
il...@google.com <il...@google.com> #6
re...@gmail.com <re...@gmail.com> #7
ne...@gmail.com <ne...@gmail.com> #8
- Changing tab with the bottom bar resets the state and backstack of the previous tab/fragment, so our users are completely losing their navigation history (this is correctly implemented in Google Photos app)
- Pressing back from the root of one tab shows the initial tab/fragment instead of leaving the app"
be...@gmail.com <be...@gmail.com> #9
ma...@gmail.com <ma...@gmail.com> #11
bm...@gmail.com <bm...@gmail.com> #12
an...@backx.org <an...@backx.org> #13
il...@google.com <il...@google.com> #14
Feel free to check out the AndroidX source code and contribution instructions at
mi...@gmail.com <mi...@gmail.com> #15
"Bottom navigation behaves differently on Android and iOS. When you select a bottom navigation item (one that’s not currently selected), each platform displays different outcomes:
On Android: the app navigates to a destination’s top-level screen. Any prior user interactions and temporary screen states are reset, such as scroll position, tab selection, and in-line search.
On iOS: the destination reflects the user’s prior interaction. If the user previously visited that section of the app, they return to the last screen viewed (with its prior state preserved, if possible). Otherwise, the app navigates to the top-level screen.""
ev...@willowtreeapps.com <ev...@willowtreeapps.com> #16
> Default platform navigation can be overridden when needed to improve the user experience. For example, an Android app that requires frequent switching between sections can preserve each section’s state. Or, an iOS app can return users to the top-level screen (or reset their scroll position) if it better suits the use case.
I think providing an easy option to save each section's state is still worth providing as an option."
il...@google.com <il...@google.com> #17
at...@gmail.com <at...@gmail.com> #18
tt...@appbird.com <tt...@appbird.com> #19
tt...@appbird.com <tt...@appbird.com> #20
[Deleted User] <[Deleted User]> #21
ig...@gmail.com <ig...@gmail.com> #22
mi...@gmail.com <mi...@gmail.com> #23
[Deleted User] <[Deleted User]> #24
il...@google.com <il...@google.com> #25
One very conscious decision we made for Navigation 1.0.0 was to depend on the 28.0.0 Support Library. This means that, out of the box, we are limited to the APIs and behavior contained within. Fragments, the default NavHost+Navigator implementation provided out of the box, does not support multiple back stacks within a single FragmentManager. Even more unfortunately, Fragments do not offer an API for a system built on top of it (such as Navigation) to access the saved instance state and non configuration instance state (i.e., ViewModels) needed to write our own multiple back stack implementation while still using a single FragmentManager.
With that in mind, we'll be doing two things:
1. Short term: provide a public sample that shows our recommended implementation of multiple back stacks with Navigation using the current APIs (i.e., a separate NavHostFragment and navigation graph for each bottom navigation item). This is a top priority for us right now, only superseded by fixing issues blocking the 1.0 release.
2) Medium term: build the correct API on Fragments so that they can properly support multiple simultaneous back stacks, including properly saving and restoring saved instance state and non configuration instance state for all of the Fragments on all of the back stacks. This work is currently in an exploratory stage and, while I'm hopeful, I cannot offer a timeline or promise that this work will succeed.
Immediately following the 1.0 stable release, Navigation will move to depend on AndroidX (similar to how Paging and other Architecture Components switched to AndroidX), allowing us to be in a position to take advantage of the work in #2 to bring multiple back stack support to Navigation in a way that supports both Fragments as well as offers a generic API for other Navigators to provide the same functionality."
nobody@google.com <nobody@google.com> #26
se...@gmail.com <se...@gmail.com> #27
Regarding the short term plan: Have you published a public sample of how to implement this yet? If so can you provide a link?
jo...@powerschool.com <jo...@powerschool.com> #28
il...@google.com <il...@google.com> #29
This sample uses multiple NavHostFragments, one for each bottom navigation tab, to work around the current limitations of the Fragment API in supporting multiple back stacks.
We'll be proceeding with the Fragment API to support multiple back stacks and the Navigation API to plug into it once created, which will remove the need for anything like the NavigationExtensions.kt file. We'll continue to use this issue to track that work.
de...@gmail.com <de...@gmail.com> #30
There is an issue though: Clicking on Bottom nav tab should bring you back to the back to the first screen in the nav graph,
Right now clicking on bottom nav tab doesn't do anything, the only way back is to click back arrow on the toolbar
Thanks :)
il...@google.com <il...@google.com> #31
The Material Design guidelines do not specify any default behavior for reselected a tab:
[Deleted User] <[Deleted User]> #32
[Deleted User] <[Deleted User]> #33
de...@gmail.com <de...@gmail.com> #34
Kotlin is first class language, but even if you don't write in Kotlin, it's not difficult to convert the sample to Java (logic is the same)
va...@gmail.com <va...@gmail.com> #36
1) Nav Door Item 1
Bottom Nav Item1, Bottom Nav Item 2
2) Nav Door Item 2
Bottom Nav Item3, Bottom Nav Item 4
Navigating across top level multi stack retaining states for both top level and child level multi-stacks.
ni...@gmail.com <ni...@gmail.com> #37
Sorry if I am missing something trivial here but I took a look at the NavigationAdvancedSample and it does not mention
how one could handle navigation to items created by onCreateOptionsMenu. I tried it out but couldn't get it to work.
Could the workaround sample be updated to show how that might be achieved? or if someone has a clue :)
mo...@gmail.com <mo...@gmail.com> #38
kotlin.TypeCastException: null cannot be cast to non-null type androidx.navigation.fragment.NavHostFragment
at net.telekom.navigationtest.NavigationExtensionsKt$setupItemReselected$1.onNavigationItemReselected(NavigationExtensions.kt:186)
what are the requirements to implement this ?
um...@gmail.com <um...@gmail.com> #39
ph...@bayfmail.com <ph...@bayfmail.com> #40
rm...@gmail.com <rm...@gmail.com> #41
fixed it by making sure that each menu item @+id matches the file name of
the corresponding navigation graph
On Thu, Apr 4, 2019 at 6:54 AM <buganizer-system@google.com> wrote:
ri...@gmail.com <ri...@gmail.com> #42
#37 this is something that is done relatively easy if the fragment you want to navigate to, is included in the corresponding navigation_graph.xml
So under this assumption, someone should provide setHasOptionsMenu(true) in onCreateView and setup the desired menu.xml in onCreateOptionsMenu. Then in onOptionsItemSelected you can easily perform the following navigation by
val navController = findNavController()
navController.navigate(R.id.action_id)
However, be aware that at the moment, the navigation component does not set the menu items properly for each fragment. If a fragment has an options menu and then the others does not clear the menu at the time they get (re)created then the options menu wrongly continues to be visible.
In addition, I would like to know if there is a workaround on how someone could navigate to a fragment that has to be common for all the navigation graphs, in the advanced navigation sample. To be provide more context, lets assume a screen like global app "search" that the user is supposed to access by clicking on a menu item. At the current implementation of the sample someone would have to include the "search" fragment in every graph, define the appropriate action and implement my proposition to #38. Although this feels wrong and defeats the purpose of navigation component IMHO.
It would be great, if someone could provide me some feedback either in the aforementioned logic or possible workaround
ag...@gmail.com <ag...@gmail.com> #43
dt...@gmail.com <dt...@gmail.com> #44
[Deleted User] <[Deleted User]> #45
mo...@gmail.com <mo...@gmail.com> #46
da...@gmail.com <da...@gmail.com> #47
But there are some fragments (with complex layout structure) that the cost of rebuilding them is higher than their occupied Memory cost
iv...@gmail.com <iv...@gmail.com> #48
ho...@gmail.com <ho...@gmail.com> #49
1- The app crashes sometimes(I couldn't find why)
2- If you have common destinations in your graph you should add them in all graphs otherwise your app will crash. For example, if your app shows product destination in graph1, and if the user is on graph2 and he/she clicks on a notification that opens product destination(product destination is in graph1), your app will crash because graph2 does not have product destination
I just waste 1 week of my time, with this ugly component
[Deleted User] <[Deleted User]> #50
al...@gmail.com <al...@gmail.com> #51
mi...@joyn.de <mi...@joyn.de> #52
Component used: Navigation
Version used: 2.0.0, 2.1.0-alpha04
Devices/Android versions reproduced on: Any
If this is a bug in the library, we would appreciate if you could attach:
- Sample project to trigger the issue (please see attached project)
How to reproduce:
In the current project
1. Create a deeplink for navigation to About fragment ( adb shell am start -W -a android.intent.action.VIEW -d "
2. Click on one of the buttons (REGISTER or BLANK) in About fragment in order to navigate to corresponding destination.
3. App crashes with an exception: java.lang.IllegalArgumentException: navigation destination com.example.android.navigationadvancedsample:id/action_blankFragment is unknown to this NavController.
te...@googlemail.com <te...@googlemail.com> #53
ro...@gmail.com <ro...@gmail.com> #54
ke...@gmail.com <ke...@gmail.com> #55
ph...@visibacare.com <ph...@visibacare.com> #56
il...@google.com <il...@google.com>
so...@gmail.com <so...@gmail.com> #57
ad...@gmail.com <ad...@gmail.com> #58
ro...@gmail.com <ro...@gmail.com> #59
ha...@live.com <ha...@live.com> #60
mo...@gmail.com <mo...@gmail.com> #61
ki...@gmail.com <ki...@gmail.com> #62
sh...@gmail.com <sh...@gmail.com> #63
missing in current navigation component.
But anyway I'd like to see someone is working on it.
Regards,
Luke Shan
Email: shanyuliang@gmail.com
* Started Android development since 2009;
* 6 years' experience on Mainframe platform;
* 2 years' experience on Microsoft platform;
* Certified DB2 V8.1 Administrator for z/OS, Windows and Linux and
Certified Java Programmer for Java SE5;
On Tue, Sep 24, 2019 at 9:41 AM <buganizer-system@google.com> wrote:
mo...@gmail.com <mo...@gmail.com> #64
il...@google.com <il...@google.com> #65
As per the public hotlists, this is expected as part of Fragment 1.3 and Navigation 2.3. That's what we're continuing to work towards.
aa...@marinosoftware.com <aa...@marinosoftware.com> #66
am...@gmail.com <am...@gmail.com> #67
Please provide a general solution not just the BottomNavigationBar
il...@google.com <il...@google.com> #68
- A Fragment specific API to ensure that the state of Fragments on multiple back stacks is saved
- A NavController API that provides the generic framework that allows any Navigator (including FragmentNavigator) to support multiple back stacks
- New APIs in NavigationUI to allow you to control whether setupWithNavController() uses a single back stack style model (the current model) or multiple back stacks when using a BottomNavigationView or NavigationView
So if you have custom UI elements or want to have more direct control, you'll be able to use the NavController level APIs.
as...@gmail.com <as...@gmail.com> #69
va...@gmail.com <va...@gmail.com> #70
If the answer is yes, an example of how to handle the following use case would be welcome:
BottomNavView with fragments A and B. Both can navigate to a fragment C. From there on out the navigation would look exactly the same. Will it be possible to handle this case with a single nav.xml but multiple back stacks?
il...@google.com <il...@google.com> #71
We'd still recommend using <include> tags and splitting up your graph into maintainable portions though as per the documentation:
as...@gmail.com <as...@gmail.com> #72
jo...@gmail.com <jo...@gmail.com> #73
af...@gmail.com <af...@gmail.com> #74
FATAL EXCEPTION: main
Process: com.xxx.xx.develop, PID: 20784
java.lang.IllegalStateException: Fragment HomeFragment{ca12844} (f2a95b7f-5df3-4106-b55b-b09067a8accb)} not associated with a fragment manager.
at androidx.fragment.app.Fragment.getParentFragmentManager(Fragment.java:945)
at androidx.navigation.fragment.NavHostFragment.findNavController(NavHostFragment.java:107)
at androidx.navigation.fragment.FragmentKt.findNavController(Fragment.kt:29)
at com.principles.pia.ui.home.HomeFragment$setUpViewModel$1.invoke(HomeFragment.kt:83)
at com.principles.pia.ui.home.HomeFragment$setUpViewModel$1.invoke(HomeFragment.kt:32)
at com.principles.pia.ui.home.items.BookItem$bind$$inlined$apply$lambda$1.onClick(BookItem.kt:22)
at android.view.View.performClick(View.java:6256)
at android.view.View$PerformClick.run(View.java:24701)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Does this look like a problem that is being tracked by this
For example we have two bottom nav tabs, per AdvancedSample, two nav graphs, each containing the following destinations: [A1, A2, A3] and [B1, B2, B3] (where A1 and B1 are corresponding starDestinations). If the app needs to be able to navigate A2->B3, would it be possible?
yg...@gmail.com <yg...@gmail.com> #75
yg...@gmail.com <yg...@gmail.com> #76
il...@google.com <il...@google.com> #77
Welcome to 2020, multiple back stacks issue. Throughout this update I'll be using Markdown syntax, so make sure to hit the 'Use the new UI' button on the top of the page to switch over to the new UI and the markdown goodness.
As mentioned in 2.3.0-alpha01
and the required support in Fragment 1.3.0-alpha01
once the FragmentManager
), fixing that has exposed a number of other issues so far (many of which were released in
However, this additional layer of work was not anticipated in the above 2.3.0-alpha01
Instead, we'll be releasing Navigation 2.3.0-alpha01
without multiple back stack support. Our plan is to finish up the Fragment rework in the upcoming Fragment 1.3.0-alpha01
release and ensure that everything works better than ever in the single back stack world that is FragmentManager
today. Oh, and get Navigation 2.3.0 to stable as soon as possible.
I've updated the public hotlists to denote that multiple back stack support is now tentatively scheduled for Navigation 2.4.0-alpha01
and Fragment 1.4.0-alpha01
, respectively. If everything goes better than expected, it may be earlier than that.
Please be considerate when replying to this issue. It does notify everyone who has starred this issue.
ya...@gmail.com <ya...@gmail.com> #78
[Deleted User] <[Deleted User]> #79
al...@gmail.com <al...@gmail.com> #80
lv...@gmail.com <lv...@gmail.com> #81
am...@gmail.com <am...@gmail.com> #82
I tried the sample but its not cutting it.. Having this baked into the navigation graphs would make life so much better!
co...@gmail.com <co...@gmail.com> #83
vu...@gmail.com <vu...@gmail.com> #84
he...@gmail.com <he...@gmail.com> #85
ma...@gmail.com <ma...@gmail.com> #86
Please be considerate when replying to this issue, because hundreds of people will get emails for unhelpful contributions.
ia...@gmail.com <ia...@gmail.com> #87
an...@gmail.com <an...@gmail.com> #88
So please for the love of God read and don't reply for asking status update or any irrelevant things. You're notifying hundreds of people that starred this issue for meaningless info.
gr...@gmail.com <gr...@gmail.com> #89
My solution:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val appBarConfigurationIds = setOf(R.id.fragmentTab1, R.id.fragmentTab2, R.id.fragmentTab3, R.id.fragmentTab4)
val appBarConfiguration = AppBarConfiguration(appBarConfigurationIds)
setupActionBarWithNavController(navController, appBarConfiguration)
bottomNavigationView.setOnNavigationItemSelectedListener { menuItem ->
if (menuItem.itemId == navController.currentBackStackEntry?.destination?.id)
return@setOnNavigationItemSelectedListener false
appBarConfigurationIds.forEach { fragmentId ->
if (fragmentId == menuItem.itemId) {
navController.navigate(fragmentId, null, NavOptions.Builder() <--- M
.setLaunchSingleTop(true) <--- A
.setPopUpTo(navController.currentDestination!!.id, true) <--- G
.build()) <--- I
return@setOnNavigationItemSelectedListener true <--- C
}
}
false
}
navController.addOnDestinationChangedListener { controller, destination, arguments ->
if (appBarConfigurationIds.indexOf(destination.id) != -1) {
controller.graph.startDestination = destination.id// <--- MAGIC
}
}
}
override fun onSupportNavigateUp() = navController.navigateUp()
private var lastBackPressed = 0L
override fun onBackPressed() {
if (navHostFragment.childFragmentManager.backStackEntryCount == 0) {
if (lastBackPressed + 1000 > System.currentTimeMillis()) {
super.onBackPressed()
} else {
lastBackPressed = System.currentTimeMillis()
toast("Double tap for exit")
}
} else
super.onBackPressed()
}
}
ib...@gmail.com <ib...@gmail.com> #90
so...@gmail.com <so...@gmail.com> #91
gu...@gmail.com <gu...@gmail.com> #92
ka...@salesforce.com <ka...@salesforce.com> #93
There's a workaround provided the
I'd like to know any updates from Google to officially support this kinda very common requirement, thanks
il...@google.com <il...@google.com> #94
As per
As seen on the 1.3.0-rc02
release before the stable release, thus clearing the way entirely for multiple back stacks (as mentioned in
Our own internal API design process has reached the point where we have a firm direction and you should begin to see changes come through attached to this bug as we build up to the final APIs to support multiple back stacks at the Fragment and Navigation level.
This will include:
- The Fragment APIs for supporting multiple back stacks (thus enabling multiple back stacks even if you do not use Navigation)
- The generic Navigation API that will allow any Navigator (be it Fragments, Compose, etc) to support multiple back stacks
- Rework of the existing Navigators to support multiple back stacks out of the box
- The APIs in
NavigationUI
and other surfaces to allow you to easily opt in to using multiple back stacks
I'd ask that you hold your comments on the intermediate steps along the way as much of it will make more sense when taken as a whole once we release the first alphas (still planned for Fragment 1.4.0-alpha01
and Navigation 2.4.0-alpha01
). Definitely expect a more thorough run through of how to use of these APIs via documentation, samples (including updating the NavigationAdvancedSample
to use the new APIs), blog posts, videos, and everything else at that point and onward. Besides seeing each commit come through on this issue, we'll also make sure to point out when a first snapshot is available with working APIs for those of you who would like an early preview before the first alpha releases.
Again, please keep in mind the many people who get emailed for each comment on this issue - let's continue to keep this as a good channel for updates and not for general discussion or requests for additional progress updates.
ap...@google.com <ap...@google.com> #95
Branch: androidx-main
commit ce3bc9455ff4eb607601b5a417f5248e93507381
Author: Ian Lake <ilake@google.com>
Date: Thu Jan 21 15:47:27 2021
Track whether an Op is associated with the topmost fragment
Multiple back stacks involve saving and later restoring the
set set of FragmentTransactions that make up the back stack
(via addToBackStack()). The replace() operation is a
unique case where you don't need to know what fragment you
are replacing - it just operates on the topmost fragment
for that container.
Due to how expandOps() works, that initial OP_REPLACE
is lost, replaced by the more primitive operations
(namely, OP_UNSET_PRIMARY_NAV, OP_REMOVE, and OP_ADD).
However, in order to save that FragmentTransaction for
later restoration in the multiple back stack case, we
need to know that the OP_REMOVE doesn't apply to a
specific fragment, but instead just the topmost
fragment of the container.
By tracking this information, we ensure that
you can safely restore a set of FragmentTransactions
(i.e., a back stack) onto the FragmentManager even
if changes have been made between saving and restoring
that back stack.
As an example, let's say the you have an initial fragment
in a container of A and two FragmentTransactions that
use addToBackStack() that called replace() with B and C,
respectively. In the multiple back stack world, you could
save both of those FragmentTransactions and return to only
A. You could then create new FragmentTransactions with
addToBackStack() to replace A with D and E, and then later
restore the back stack previously saved. By doing so,
the FragmentTransaction that previously replaced A with B
would now replace E (the topmost fragment of the container)
with B, followed by a replacement of B with C. Thus, you
would be on a stack that had A -> D -> E -> B -> C.
There's still more work needed to build up the rest of the
Fragment APIs for multiple back stacks - this is just
the first step on the underlying implementation.
Test: existing tests pass
BUG: 80029773
Change-Id: I8432e9043eeb14c05b1a121d94e00722cff31688
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackState.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
ap...@google.com <ap...@google.com> #96
Branch: androidx-main
commit 10604f16c11ed787d0f0e9ac94dc509532987d14
Author: Ian Lake <ilake@google.com>
Date: Mon Jan 25 17:44:05 2021
Add API for saving the back stack
The Fragment back stack is made up of separate
BackStackRecords, also known as transactions (as they
implement FragmentTransaction and that's the public
API used to create them). While a popBackStack()
operation will reverse the transaction and destroy
all of the no longer referenced fragments, to *save*
the state we need a new type of operation.
This operation is called saveBackStack() and takes the
name of the back stack entry (the one set via
addToBackStack()). This required converting some
common code (finding the correct index on the back stack)
so that it is useable by both pop and save.
This does not yet actually do any saving, nor is the
restore half of the equation built yet, but this is
the first step down that path.
Test: new SaveRestoreBackStackTest suite
BUG: 80029773
Relnote: N/A
Change-Id: I661f33c0ea7bb67338f7d9e75f8e8b8454d2bc21
M fragment/fragment/api/current.txt
M fragment/fragment/api/public_plus_experimental_current.txt
M fragment/fragment/api/restricted_current.txt
A fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
ap...@google.com <ap...@google.com> #97
Branch: androidx-main
commit b95c6d3b57d048a965c9062f9ae595a88a034e3d
Author: Ian Lake <ilake@google.com>
Date: Mon Feb 01 15:58:33 2021
Ensure saveBackStack() is self contained
A key part to saving a back stack is to be
able to later restore that same back stack.
As such, we need to ensure that the
FragmentTransactions that are being saved
are self contained - i.e., that the only
fragments they specifically mention are
added as part of those transactions. By
ensuring that the saved transactions are
self contained, we can ensure that they
can be correctly restored even if the
underlying state of the FragmentManager
is changed between the save and restore
operations.
This builds upon the previous topmost
fragment change so as to continue to allow
operations like replace() which don't
explicitly mention previously added fragments.
As part of this, generateOpsForPendingActions() has
been made more resilient to crashes - if a
generateOps() call crashes, it still throws the
exception, but the set of pending actions that
crashed FragmentManager will now be cleared out
so that they are not reprocessed any time later
if something (like our test suite...) catches
exceptions thrown by executePendingOperations().
Test: new savePreviouslyReferencedFragment test
BUG: 80029773
Change-Id: I0bde3c27f415990c2918d98a79ea76c3d0c6b55e
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
al...@gmail.com <al...@gmail.com> #98
I have been using the workaround proposed for using multiple back stacks navigation in my app - [CheSScan](
Thanks!
ap...@google.com <ap...@google.com> #99
Branch: androidx-main
commit d0752ab5b18e85ac5d45f768bce8ad0a8ed36c3b
Author: Ian Lake <ilake@google.com>
Date: Thu Feb 11 14:39:52 2021
Ensure all saved transactions have reordering allowed
The documentation specifically calls out that
setReorderingAllowed(true) should be used on each
FragmentTransaction (see
but this is moves from a 'should use' to a
'must use' pattern when it comes to saving the
back stack and the FragmentTransactions on it.
This is because setReorderingAllowed(true) is
critical to ensuring that a set of back to back
transactions are executed as an atomic operation,
thus preventing any intermediate fragments (those
that are added and then moved onto the back stack)
from moving through lifecycle states unnecessarily.
By checking this when executing saveBackStack(), we
ensure that the later restore operates as expected.
Test: new saveNonReorderingAllowedTransaction test
BUG: 80029773
Change-Id: Ied3b2a221202ca4626975853b741c76edd08f978
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
ap...@google.com <ap...@google.com> #100
Branch: androidx-main
commit fe00de00ab8a008405810a7f1ef3c9826d5c3cd7
Author: Ian Lake <ilake@google.com>
Date: Thu Feb 18 16:57:47 2021
Add BackStackState infrastructure
A saved back involves two main components:
1. The set of FragmentTransactions that make
up that saved back stack
2. The set of Fragments that were added
as part of that back stack
This is encapsulated in the new BackStackState
class. This is class that will eventually be
created by saveBackStack() and later used by
restoreBackStack() to restore the stack. Those
integration points are coming in follow up CLs:
this is solely the Parcelable used to store this
state.
Test: new BackStackRecordTest test suite
BUG: 80029773
Change-Id: I1658c01fdf7af8941436db96000e91796b823108
A fragment/fragment/src/androidTest/java/androidx/fragment/app/BackStackRecordTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackRecordState.java
A fragment/fragment/src/main/java/androidx/fragment/app/BackStackState.java
ap...@google.com <ap...@google.com> #101
Branch: androidx-main
commit 7db1719dba9c8646c9dbcda7bf0a61926c1789df
Author: Ian Lake <ilake@google.com>
Date: Thu Feb 25 15:42:37 2021
Disallow retained fragments in saveBackStack()
When saving the back stack, all fragments have
their state and non-config state saved before they
are fully destroyed. This, by necessity, also means
fully destroying any child fragments (and their
child fragments, etc.), saving the state of those as
well. This state is then held until restoreBackStack()
is called (or the entire FragmentManager is
permanently destroyed).
This state-only saving means that retained fragments,
either directly or as child fragments, are not supported
as their contract is that they are not destroyed
until they are permanently removed. Instead, developers
should use ViewModels to store any non-config state.
Test: new SaveRestoreBackStackTest tests
BUG: 80029773
Change-Id: I01f94cbfae3f3850e8a4efe84e6576e408f68ef8
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
ap...@google.com <ap...@google.com> #102
Branch: androidx-main
commit f54b6d3d78139605391592d689f2f3c5c9e55197
Author: Ian Lake <ilake@google.com>
Date: Thu Feb 25 17:19:43 2021
Add infra for saving/restoring BackStackStates
Each FragmentManager is responsible for tracking
the set of BackStackState objects that have been
saved via saveBackStack() and the associated name.
This state needs to be saved and restored alongside
the rest of the FragmentManager's state to ensure
that the state is available for later restoration
even after one or more configuration changes.
This adds the underlying infrastructure for saving
and restoring the state objects that will later be
populated by saveBackStack().
Test: existing tests that save/restore state still pass
BUG: 80029773
Change-Id: I5776c50143deb4d7679c581a2e7655d5c2655443
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManagerState.java
di...@gmail.com <di...@gmail.com> #103
je...@gmail.com <je...@gmail.com> #104
[Deleted User] <[Deleted User]> #105
ap...@google.com <ap...@google.com> #106
Branch: androidx-main
commit a7835d060734f7a3dc7acc457c822330ef64d5a2
Author: Ian Lake <ilake@google.com>
Date: Mon Mar 15 16:54:08 2021
Build infrastructure for collapsing transactions
Right before a FragmentTransaction is executed,
operations like replace() and setPrimaryNavigationFragment()
are expanded into multiple operations:
- A replace() becomes one or more remove() operations
plus an add() (unless you specifically call add()
earlier in the transaction...for some reason).
- setPrimaryNavigationFragment() becomes an unset of the
previous primary navigation fragment and then the set
of the new primary navigation fragment
These expanded operations can reference previously
created fragments, despite them not being explicitly
mentioned when building the FragmentTransaction. When
it comes to saving and later restoring these transactions,
we need to collapse the transactions back down into their
original form so that:
1) they don't reference other fragments not being saved
2) they can be re-expanded later onto a new back stack
This CL swaps out the term 'topmost fragment' with
'from expanded op' to better mark which operations
came from one of these expansions. This then allows
us to write the infrastructure and tests to ensure
that a collapse puts the transaction back into
the previous state that will later be used by
saveBackStack().
Test: updated and new BackStackRecordTest tests pass
BUG: 80029773
Change-Id: Iadd95c557b759bd95f07d89cadf62b44d4971956
M fragment/fragment/src/androidTest/java/androidx/fragment/app/BackStackRecordTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackRecordState.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
su...@gmail.com <su...@gmail.com> #107
I am facing issue with explicit deeplinking, which is not launching the respected screen, Any update on this issue, or any workaround.
[Deleted User] <[Deleted User]> #108
ap...@google.com <ap...@google.com> #109
Branch: androidx-main
commit cac5a59e08bff1fc47a721d112fa5289d3ddf5bc
Author: Ian Lake <ilake@google.com>
Date: Thu Mar 25 17:43:49 2021
Make saveBackStack() actually save the back stack state
The saveBackStack() API is responsible for a number of
things:
1) Popping the saved FragmentTransactions off the back
stack - this was done in previous CLs.
2) Saving the actual FragmentTransactions themselves
so that they can later to restored
3) Save the state of each Fragment included in
those FragmentTransactions
This change seeks to address the core points of #2
and #3. Now, when saveBackStack() is called, all
Fragments will go through onSaveInstanceState(), either
immediately after onStop() (mirroring the behavior of
the activity being torn down due to a configuration
change, etc.) or immediately before onDestroy() (in
cases where the Fragment is already stopped - such as
when it is on the back stack).
The FragmentTransactions themselves are also
collapsed (i.e., replacing the expanded set of
REMOVE+ADD operations with the original REPLACE operation)
and have their state saved, readying them for later
restoration.
Note that this change does *not* handle nonconfig state
(ViewModels). That will be done in a follow up CL.
Test: saveBackStack test passes
BUG: 80029773
Change-Id: I37327ab6a7deab0d72d5be1a251c0d5e3a280362
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
ap...@google.com <ap...@google.com> #110
Branch: androidx-main
commit 5104c7c386ea69551616e8723cb87e5dbd27f6ad
Author: Ian Lake <ilake@google.com>
Date: Mon Mar 29 13:43:30 2021
Add the API to restore a saved back stack
Saving the back stack is only half of the API;
the other half is the ability to later restore
that back stack onto the FragmentManager. This
is the role of the restoreBackStack() API. It
takes a name (the same name passed to
addToBackStack() and then later passed to
saveBackStack()) and re-instantiates all of the
FragmentTransaction and Fragment instances and
re-applies them to the FragmentManager.
Particularly, this builds on the state saving
done by saveBackStack() to ensure that every
fragment that was saved has its saved state
restored when you call restoreBackStack().
The addition of this API did expose some issues
in the previously added code, namely:
- saveBackStack() needs a callback immediately
after the FragmentTransaction pop is executed and
*before* the Fragments are destroyed. This ensures
that the right internal IDs of Fragments are saved
in the BackStackRecordState and means we can't use
the on commit runnables list and need to maintain
our own list.
- As the population of the BackStackRecordState
is asynchronous, BackStackState needs to keep a
reference to the original list created by
saveBackStack() rather than copying the entries
into its own ArrayList.
Relnote: N/A
Test: new tests pass
BUG: 80029773
Change-Id: Ib8c35cea758379374cde7c1253922e345544b3c5
M fragment/fragment/api/current.txt
M fragment/fragment/api/public_plus_experimental_current.txt
M fragment/fragment/api/restricted_current.txt
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackState.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
ap...@google.com <ap...@google.com> #111
Branch: androidx-main
commit 3645a0d738376c0035c2436ba5c53c750fe84d86
Author: Ian Lake <ilake@google.com>
Date: Tue Mar 30 16:02:51 2021
Save ViewModels when saving and restore the back stack
The most important part of calling saveBackStack() is
that the state of the fragments must be saved.
This can be roughly summarized in three parts:
1) The Fragment's saved instance state
2) The Fragment's View state
3) The Fragment's non-config state
The first two are already handled by the previous
changes, but the later one is just as important,
particularly when it comes to immediately showing
cached data. As retained fragments are not
supported when using saveBackStack(), the only
non-config state is that of ViewModels.
Besides just avoiding clearing the ViewModels when
the fragment is destroyed as part of saving the
back stack, special attention was taken to the
case where the Activity / parent Fragment is itself
destroyed. In this case, any ViewModels associated
with saved fragments must be specifically cleared as
they would not automatically be cleaned up on their
own (as their containing fragment no longer exists,
just its saved state).
Test: updated tests pass
BUG: 80029773
Change-Id: Idafc0af58e1a43893774f6ae6d7caac8bd56efb4
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManagerViewModel.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
il...@google.com <il...@google.com> #112
As per saveBackStack(name: String)
and restoreBackStack(name: String)
APIs have been added to FragmentManager
in
With the Fragment work complete, the implementation work on the Navigation side of multiple back stacks is next up - you'll continue to see changes added to this CL as that work continues.
As a reminder, that Navigation work includes:
- The generic Navigation API that will allow any Navigator (be it Fragments, Compose, etc) to support multiple back stacks
- Rework of the existing Navigators to support multiple back stacks out of the box
- The APIs in
NavigationUI
and other surfaces to allow you to easily opt in to using multiple back stacks
Also as mentioned before:
I'd ask that you hold your comments on the intermediate steps along the way as much of it will make more sense when taken as a whole once we release the first alphas (still planned for Fragment 1.4.0-alpha01
and Navigation 2.4.0-alpha01
). Definitely expect a more thorough run through of how to use of these APIs via documentation, samples (including updating the NavigationAdvancedSample
to use the new APIs), blog posts, videos, and everything else at that point and onward. Besides seeing each commit come through on this issue, we'll also make sure to point out when a first snapshot is available with working APIs for those of you who would like an early preview before the first alpha releases.
Again, please keep in mind the many people who get emailed for each comment on this issue - let's continue to keep this as a good channel for updates and not for general discussion or requests for additional progress updates. If you'd like to receive updates, please star the issue, not comment on it.
ap...@google.com <ap...@google.com> #113
Branch: androidx-main
commit b3588b98629d9552c5666a0e3a3984927ba80b0d
Author: Ian Lake <ilake@google.com>
Date: Mon Apr 05 15:51:01 2021
Add NavOptions for saving and restoring the back stack
When navigating with the NavController, the primary
mechanism is via calls to navigate(), which simply
adds the new destination to the back stack. NavOptions
are the existing mechanism for modifying that default
behavior (e.g., using launchSingleTop to ensure only
one copy of the destination is on the top of the
back stack).
Therefore NavOptions is one of the surfaces that needs
to be updated to support multiple back stacks in two ways:
- the restoreState boolean controls whether any previously
saved back stack and destination states associated with
the destination you're navigating to should be restored
- the popUpToSaveState boolean controls whether the back
stack and destination states between the current destination
and your popUpTo destination (inclusive or not) should be
saved for later restoration
Note: these APIs are not currently plugged into the
NavController or Navigators. That will be done in
follow up CLs.
Relnote: N/A
Test: Updated tests pass
BUG: 80029773
Change-Id: I7f4db810f027dd83f34c4906d4d21e73e051b35c
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/public_plus_experimental_current.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/src/androidTest/java/androidx/navigation/NavOptionsBuilderTest.kt
M navigation/navigation-common/src/main/java/androidx/navigation/NavOptions.kt
M navigation/navigation-common/src/main/java/androidx/navigation/NavOptionsBuilder.kt
M navigation/navigation-common/src/main/res-public/values/public_attrs.xml
M navigation/navigation-common/src/main/res/values/attrs.xml
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavInflater.kt
ap...@google.com <ap...@google.com> #114
Branch: androidx-main
commit 17366f6b6a267b39bcf9fab5f3b4b1dec793e748
Author: Jeremy Woods <jbwoods@google.com>
Date: Tue Apr 06 17:08:18 2021
Upgrade Navigation to use Activity 1.2.2, ToT Fragments
In preparation for navigation-fragment using the
multiple back stacks APIs added in the latest
version of Fragments, update the dependencies in
Navigation to use the latest stable Activity release
(1.2.2) and the tip-of-tree version of Fragments.
By necessity, this updates usages of deprecated
Fragment APIs (namely, startIntentSenderForResult()
and onActivityResult) to their replacements.
Relnote: "Navigation Runtime now depends on
[Activity `1.2.2`](/jetpack/androidx/releases/activity#1.2.2)."
Test: existing navigation-fragment tests still pass
BUG: 80029773
Change-Id: Iad6bec4af04c4ad748277fe7f99b87c7f5698ec6
M navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
M navigation/navigation-fragment/build.gradle
M navigation/navigation-runtime/build.gradle
ap...@google.com <ap...@google.com> #115
Branch: androidx-main
commit 95261600fd07bdfc22af2cf64c3ef58034192a1d
Author: Ian Lake <ilake@google.com>
Date: Mon Apr 12 13:57:58 2021
Add saveState parameter to popBackStack()
In addition to being able to add the
popUpToSaveState value to NavOptions, it
should also be possible to save state when
manually popping the stack via popBackStack().
Relnote: N/A
Test: ./gradlew checkApi
BUG: 80029773
Change-Id: I5517c9e86cac63266c4742c67415afdc026d8c34
M navigation/navigation-runtime/api/current.txt
M navigation/navigation-runtime/api/public_plus_experimental_current.txt
M navigation/navigation-runtime/api/restricted_current.txt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #116
Branch: androidx-main
commit bbb3729f948ca4995b15296a40cd9db6353088ee
Author: Ian Lake <ilake@google.com>
Date: Tue Apr 13 11:30:48 2021
Save the NavBackStackEntry state
When using the saveState flag on the pop operation,
all of the state associated with the popped destinations
should be saved. That includes both the saved
instance state (calling saveState() once the destination
is stopped) as well as non-config state in the form of
any ViewModels associated with the destination.
This involves associating that saved state with
the ID of the destination you've popped up to
as well as ensuring that ViewModels are not cleared
as part of the pop (but are still cleared when the
hosting ViewModelStore is cleared).
Relnote: N/A
Test: new NavBackStackEntryTest tests pass
BUG: 80029773
Change-Id: Ia5a35ec712cf5a58c3c310999bacb3c87e8cc522
M navigation/navigation-runtime/api/public_plus_experimental_current.txt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntryState.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #117
Branch: androidx-main
commit fde7cd4bf112f37061e036cfdd8c44c3af98ee77
Author: Ian Lake <ilake@google.com>
Date: Wed Apr 21 15:31:38 2021
Decouple NavBackStackEntry from NavControllerViewModel
Rather than having a compile time dependency
on the concrete NavControllerViewModel class
in NavBackStackEntry, create a new interface
that NavBackStackEntry can depend on.
Test: NavBackStackEntry tests still pass
BUG: 80029773
Change-Id: I4345c5d93359b8f0d0c21d68c12912f3ea16112b
M navigation/navigation-common/build.gradle
A navigation/navigation-common/src/main/java/androidx/navigation/NavViewModelStoreProvider.kt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavControllerViewModel.kt
ap...@google.com <ap...@google.com> #118
Branch: androidx-main
commit f57cd370acf055e004eb4bfb1e95904624a83dca
Author: Ian Lake <ilake@google.com>
Date: Wed Apr 21 15:52:15 2021
Move NavBackStackEntry to navigation-common
Move NavBackStackEntry to live in the same
artifact as Navigator.
Relnote: N/A
Test: existing tests still pass
BUG: 80029773
Change-Id: I84167184c3356e0c27cd61ae191e5ea995d40d26
M navigation/navigation-common/api/api_lint.ignore
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/public_plus_experimental_current.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/build.gradle
M navigation/navigation-common/src/main/java/androidx/navigation/NavBackStackEntry.kt
A navigation/navigation-runtime/api/current.ignore
M navigation/navigation-runtime/api/current.txt
M navigation/navigation-runtime/api/public_plus_experimental_current.txt
A navigation/navigation-runtime/api/restricted_current.ignore
M navigation/navigation-runtime/api/restricted_current.txt
M navigation/navigation-runtime/build.gradle
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntryState.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #119
Branch: androidx-main
commit 4ab8db7d2ca746a38bdde67e3ef495e83ddb0aa5
Author: Ian Lake <ilake@google.com>
Date: Fri Apr 23 14:25:17 2021
Build connection between NavController and Navigator state
Introduce the NavigatorState class. This state is owned
by the NavController, but is specifically set at the
Navigator level. Besides giving the Navigator read access
to the set of destinations on its own back stack, it
also encapsulates the add and pop operations in such
a way as to allow the Navigator to push changes back
to the NavController.
To allow for testing of a Navigator independently
of a NavController, a TestNavigatorState, provides
an alternate implementation specifically for testing
purposes.
Relnote: N/A
Test: updated and existing tests pass
BUG: 80029773
Change-Id: Id2afe4c8d428894826d0391173a162cf8c977328
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/public_plus_experimental_current.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/src/main/java/androidx/navigation/NavBackStackEntry.kt
M navigation/navigation-common/src/main/java/androidx/navigation/Navigator.kt
A navigation/navigation-common/src/main/java/androidx/navigation/NavigatorState.kt
M navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt
M navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/DialogFragmentNavigator.kt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
M navigation/navigation-testing/api/current.txt
M navigation/navigation-testing/api/public_plus_experimental_current.txt
M navigation/navigation-testing/api/restricted_current.txt
M navigation/navigation-testing/build.gradle
A navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
M testutils/testutils-navigation/build.gradle
M testutils/testutils-navigation/src/main/java/androidx/testutils/TestNavigator.kt
M testutils/testutils-navigation/src/test/java/androidx/testutils/TestNavigatorTest.kt
ap...@google.com <ap...@google.com> #120
Branch: androidx-main
commit ff14ae5dd8a1767597622e9d2c5deb27078b8a01
Author: Ian Lake <ilake@google.com>
Date: Thu Apr 22 13:12:35 2021
Add attach API to Navigators
Rather than doing initialization in the
Navigator's init, give Navigators an initial
callback on when the NavController has started
using the Navigator.
This also changes the behavior such that replacing
a Navigator after the NavController has restored
its state results in an error.
Relnote: N/A
Test: existing tests pass
BUG: 80029773
Change-Id: I2f2b8aac0541d4e084cb4b53175b6a0195a4cc59
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/public_plus_experimental_current.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/src/main/java/androidx/navigation/Navigator.kt
M navigation/navigation-common/src/main/java/androidx/navigation/NavigatorProvider.kt
M navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/DialogFragmentNavigator.kt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #121
Branch: androidx-main
commit 5c911ea7cbe26bff5091a2d0b2f9b126678eb04b
Author: Ian Lake <ilake@google.com>
Date: Mon Apr 26 17:04:31 2021
Introduce multiple back stack compatible Navigator APIs
The current Navigator APIs operated on a single
destination at a time, which made it impossible to
coordinate a set of navigate() calls or a popBackStack()
that would pop multiple destinations at once - both
of which are required to fully support the saving
and restoring of state needed to support
multiple back stacks.
In addition to supporting batch operations, these
new Navigator APIs give the Navigator direct access
to the NavBackStackEntry instance that is being
navigated to. This allows the new APIs to be
backward compatible - translating calls to the new
APIs back into the old API internally while still
allowing a Navigator to fully switch over to the
new APIs (and just not call the superclass
implementation).
The NavController was fully rebuilt to only call
the new APIs while continuing to work with
existing Navigator implementations without any
changes. The previous temporary solution required
for TestNavigator (calling the NavigatorState APIs
from the old navigate/popBackStack() methods) was
removed entirely as the default implementations
correctly update the NavigatorState.
Relnote: N/A
BUG: 80029773
Test: existing tests for all Navigators pass
Change-Id: Ia1ff09a4b76f15a35d6a9c520687033d6f1565a7
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/public_plus_experimental_current.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/src/main/java/androidx/navigation/Navigator.kt
M navigation/navigation-compose/api/current.txt
M navigation/navigation-compose/api/public_plus_experimental_current.txt
M navigation/navigation-compose/api/restricted_current.txt
M navigation/navigation-dynamic-features-runtime/api/current.ignore
M navigation/navigation-dynamic-features-runtime/api/current.txt
M navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt
M navigation/navigation-dynamic-features-runtime/api/restricted_current.ignore
M navigation/navigation-dynamic-features-runtime/api/restricted_current.txt
M navigation/navigation-fragment/api/current.ignore
M navigation/navigation-fragment/api/current.txt
M navigation/navigation-fragment/api/public_plus_experimental_current.txt
M navigation/navigation-fragment/api/restricted_current.ignore
M navigation/navigation-fragment/api/restricted_current.txt
M navigation/navigation-runtime/api/current.ignore
M navigation/navigation-runtime/api/current.txt
M navigation/navigation-runtime/api/public_plus_experimental_current.txt
M navigation/navigation-runtime/api/restricted_current.ignore
M navigation/navigation-runtime/api/restricted_current.txt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
M navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorProvider.kt
M testutils/testutils-navigation/src/main/java/androidx/testutils/TestNavigator.kt
M testutils/testutils-navigation/src/test/java/androidx/testutils/TestNavigatorTest.kt
ap...@google.com <ap...@google.com> #122
Branch: androidx-main
commit cf47135438d553629daa94c42f3d37502eb2fba7
Author: Ian Lake <ilake@google.com>
Date: Tue Apr 27 17:50:04 2021
Convert ComposeNavigator+NavHost to new Navigator APIs
Utilize the new Navigator APIs and specifically
the NavigatorState within ComposeNavigator and
NavHost. This ensures a single source of truth from
the NavController to the NavigatorState to the
NavHost.
Due to the use of DisposableEffect, the NavHost
composes at least once before the graph is set
(and therefore before the NavigatorState is available).
This logic is encapsulated within ComposeNavigator
such that the NavHost can always assume the
back stack is available.
The ComposeNavigatorTest suite was redone to
focus on the logic that ComposeNavigator now contains
around the back stack, thus avoiding duplicating the
logic already tested in the base NavController and
Navigator tests.
Relnote: N/A
BUG: 80029773
Test: updated ComposeNavigatorTest tests pass
Change-Id: I0698d2a5e0e7bf8379bab8636f54882d33a464b3
M navigation/navigation-compose/api/current.txt
M navigation/navigation-compose/api/public_plus_experimental_current.txt
M navigation/navigation-compose/api/restricted_current.txt
M navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/ComposeNavigatorTest.kt
M navigation/navigation-compose/src/main/java/androidx/navigation/compose/ComposeNavigator.kt
M navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHost.kt
ap...@google.com <ap...@google.com> #123
Branch: androidx-main
commit 6bd5c055e363ec648db8e1c9afa781935d6542ae
Author: Ian Lake <ilake@google.com>
Date: Thu Apr 29 15:17:37 2021
Add support for restoring state
Hook up the restoreState to calls to navigate(),
allowing the NavBackStackEntry state to be restored
back to the state it was originally saved in.
This means that even if the underlying Navigator
does not participate in saving state, the
NavController will still navigate() to the same set
of destinations with the same NavBackStackEntry state
when the saveState/restoreState APIs are used.
BUG: 80029773
Test: New NavControllerTest tests pass
Change-Id: I4b69f189314e6edc998391c29c35ab1c4d35fa2c
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #124
Branch: androidx-main
commit b4edb9532c81542cdc62fb384d9bfb06bfcb73e0
Author: Ian Lake <ilake@google.com>
Date: Mon May 03 16:40:01 2021
Fix popUpTo+restoreState when inclusive=false
In cases where you use popUpTo and inclusive=false,
the back stack state needs to be associated not only
with the destination you've directly passed to
popUpTo, but also with the destination that was
actually popped.
In addition, this state also needs to be associated
with the parents of those destinations specifically
when the destination is the start destination of the
graph so that navigating to the graph itself is
treated the same as navigating to the start destination
when it comes to restoring state.
E.g., let's say you have three nested graphs: A, B, and C,
each with a respective start destination of A', B', and
C'. As per the Principles of Navigation, you should
always keep the start destination of your graph (A') on
the back stack. Therefore, the much more common case
is to use popUpTo(A') with inclusive=false when navigating
to B or C (or back to A). By adjusting the logic around
saving the state, navigating from B to C will save the
state of B to B, even though the popUpTo was set to A'.
Similarly, the state of A' (and notably, any destinations
stacked on top of it) will be restored when you navigate
to A with restoreState=true.
With this change, the BottomBarNavDemo for Navigation Compose
was updated to use the new restoreState and saveState flags
and now the state of the Scrollable destination is properly
saved and restored when you swap between the Scrollable
and Dashboard tabs by tapping on the bottom nav.
BUG: 80029773
Test: new NavControllerTest tests passes
Change-Id: I4ce337d269fe0db5ee424d5f47e64868c5a1a3a9
M navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/BottomBarNavDemo.kt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #125
Branch: androidx-main
commit ff325dad7ef332217b2cb9ae1428d24bb10fbc3b
Author: Ian Lake <ilake@google.com>
Date: Wed May 05 14:55:58 2021
Ensure TestNavigatorState updates the Lifecycle correctly
The TestNavigatorState serves the role of
"NavController" when building isolated tests
for a Navigator. As such, it owns the logic for
updating and maintaining the state of each
NavBackStackEntry added to it.
As such, the TestNavigatorState now updates
the Lifecycle of each NavBackStackEntry
as it is added and popped from the state's
back stack, mirroring the behavior of
NavController.
Relnote: N/A
Test: new TestNavigatorStateTest
BUG: 80029773
Change-Id: I92b09989a7d9bc63d52747eef40f04d75a43cc0d
M navigation/navigation-testing/api/current.txt
M navigation/navigation-testing/api/public_plus_experimental_current.txt
M navigation/navigation-testing/api/restricted_current.txt
A navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavigatorStateTest.kt
M navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
M testutils/testutils-navigation/build.gradle
M testutils/testutils-navigation/src/test/java/androidx/testutils/TestNavigatorTest.kt
ap...@google.com <ap...@google.com> #126
Branch: androidx-main
commit ce44b5214ef9ce0a2b478298554c98854d27f1b6
Author: Ian Lake <ilake@google.com>
Date: Thu May 06 15:04:48 2021
Make NavBackStackEntry's ID public
Rather than rely on each Navigator to
construct its own idea of a unique
key for a NavBackStackEntry (e.g., using
its position in the back stack or the
destination ID), we'd like to encourage
using the unique ID of the NavBackStackEntry.
Relnote: "The unique ID of a `NavBackStackEntry`
is now exposed as part of its public API."
Test: ./gradlew checkApi
BUG: 80029773
Change-Id: Ie033a9056cead23ef9bcff1c52e67172c459b0f2
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/public_plus_experimental_current.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/src/main/java/androidx/navigation/NavBackStackEntry.kt
M navigation/navigation-common/src/main/java/androidx/navigation/NavViewModelStoreProvider.kt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerViewModelTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntryState.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavControllerViewModel.kt
M navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
ap...@google.com <ap...@google.com> #127
Branch: androidx-main
commit 4485a5102b93d0551db020bdbf1f78baa6b47b3b
Author: Ian Lake <ilake@google.com>
Date: Thu May 06 21:55:58 2021
Convert FragmentNavigator to Navigator v2 APIs
Convert FragmentNavigator and its subclass,
DynamicFragmentNavigator, to the Navigator v2 APIs.
Relnote: N/A
BUG: 80029773
Test: updated tests pass
Change-Id: I983269785ad2b5c9e74bd6b52cfee5d5698b0fa4
M navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigator.kt
M navigation/navigation-fragment/api/current.ignore
M navigation/navigation-fragment/api/current.txt
M navigation/navigation-fragment/api/public_plus_experimental_current.txt
M navigation/navigation-fragment/api/restricted_current.ignore
M navigation/navigation-fragment/api/restricted_current.txt
M navigation/navigation-fragment/build.gradle
M navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
M navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
ap...@google.com <ap...@google.com> #128
Branch: androidx-main
commit d4f6ac6d46cec08ee9a11b44955da4c69ec6aec3
Author: Ian Lake <ilake@google.com>
Date: Thu May 06 16:51:03 2021
Convert NavGraphNavigator to Navigator v2 APIs
Convert NavGraphNavigator and its subclass,
DynamicGraphNavigator, to the Navigation v2 APIs.
Relnote: N/A
BUG: 80029773
Test: updated tests pass
Change-Id: I735b94efb92a0275c931af30c4a669be388f9186
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/public_plus_experimental_current.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/build.gradle
M navigation/navigation-common/src/main/java/androidx/navigation/NavGraphNavigator.kt
M navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt
M navigation/navigation-dynamic-features-runtime/build.gradle
M navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt
M navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt
M navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt
ap...@google.com <ap...@google.com> #129
Branch: androidx-main
commit 5236d8017f82fcf8f193f7ab1bced55d485508e5
Author: Ian Lake <ilake@google.com>
Date: Fri May 07 11:43:37 2021
Connect Navigation and FragmentManager's state save/restore
Update FragmentNavigator to correctly save and restore
the Fragment's state when the NavController uses the
restoreState and saveState APIs.
To enable testing the save/restore separately from
NavController, this added a new restoreBackStackEntry()
API to TestNavigatorState.
Relnote: N/A
Test: new FragmentNavigatorTest tests pass
BUG: 80029773
Change-Id: I4ac261ab2195e276c93ffd63152fe2bcefa3651a
M navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
M navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
M navigation/navigation-testing/api/current.txt
M navigation/navigation-testing/api/public_plus_experimental_current.txt
M navigation/navigation-testing/api/restricted_current.txt
M navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
ap...@google.com <ap...@google.com> #130
Branch: androidx-main
commit 19cf489673a84b939bc676ba247d983f07c9959a
Author: Ian Lake <ilake@google.com>
Date: Sun May 09 15:39:23 2021
Add restoreBackStack records to the back stack
Delegate to BackStackRecord's generateOps call
in restoreBackStackState() to ensure that
restoreBackStack() results in the exact same
behavior as manually executing each
FragmentTransactions.
Importantly, this ensures that each record
is added to the FragmentManager's back stack.
Test: updated SaveRestoreBackStackTest tests pass
BUG: 80029773
Change-Id: I9f2484c9244f4cca20745623184c695ca842d3d7
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
bo...@gmail.com <bo...@gmail.com> #131
A question: with all due respect, are these automatic comments really necessary or useful? I'd like to keep my "star" on this issue, and know when it will be fixed. But the noise doesn't help. Thanks a lot!
il...@google.com <il...@google.com> #132
Re #131 - yes, they are necessary. As stated multiple times and seen in the hotlists this bug is associated with, this will be fixed with Fragment 1.4.0-alpha01 and Navigation 2.4.0-alpha01, so if you're looking for only an update on when those are released and not for updates on the progress leading up to that point, you can use the
ap...@google.com <ap...@google.com> #133
Branch: androidx-main
commit 98e0bfd1a040eb1f9f0755f0152a5f30195ea3df
Author: Ian Lake <ilake@google.com>
Date: Sun May 09 16:35:27 2021
Fix restoreBackStack() when saveBackStack() is pending
Any FragmentTransaction happens as separate stages:
1) Generate the set of transactions that need to be applied
2) Execute the transactions
3) Move the Fragments to their expected state
When calling saveBackStack() followed by restoreBackStack()
without any intervening time or specifically calls to
executePendingTransactions(), step 1 is applied to both
the saveBackStack() and restoreBackStack() commands without
step 2 and 3 actually being executed yet.
This means that saveBackStack() needs to capture enough
state while executing step 1 such that the
restoreBackStack() has enough information to generate
the proper set of FragmentTransactions. As such, the
previous approach of using an "execute runnable"
(which would only run in step 2) is not sufficient.
Instead, saveBackStack() now creates a deep copy of
the full BackStackRecord and immediately saves its
state as part of step 1, thus ensuring that it is already
available when step 1 for restoreBackStack() is available.
On the flip side, because step 2 and 3 haven't been
executed yet when restoreBackStack()'s step 1 executes,
the Fragments that would not have had their state saved
and been destroyed, meaning that BackStackState must
now consider the case where the Fragment still exists
prior to trying to find the saved state of the previously
destroyed fragment.
Test: new SaveRestoreBackStackTest test passes
BUG: 80029773
Change-Id: I147cc168d712d49f7533f51e56776506b3c7698c
M fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackState.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
ap...@google.com <ap...@google.com> #134
Branch: androidx-main
commit 62c022f23c6bcd52fa94150eba8ef3e6c09e742b
Author: Ian Lake <ilake@google.com>
Date: Sun May 09 16:49:28 2021
Enable saving state in NavigationUI by default
Ensure that any usages of NavigationUI's
onNavDestinationSelected() API or APIs that
use it internally (such as the
setupWithNavController() methods for
NavigationView and BottomNavigationView)
use the popUpTo API with saveState = true
and setRestoreState(true) to ensure that
any popped destinations have their state saved
and restored when you navigate back to that
destination (either via selecting the
same menu item again or manually using the
setRestoreState(true) API.
This means that BottomNavigationView and
NavigationView users will automatically get
multiple back stack support just by using
NavigationUI and upgrading their version
of Navigation to one that supports multiple
back stacks.
Relnote: "The `NavigationUI` methods of
`onNavDestinationSelected()`,
`BottomNavigationView.setupWithNavController()` and
`NavigationView.setupWithNavController()` now
automatically save and restore the state of
popped destinations, enabling automatic support
for multiple back stacks."
Test: tested in navigation-integration-tests testapp
BUG: 80029773
Change-Id: Ie07ca3089faca25e56e58293b49f32b795e1f30a
M navigation/navigation-ui/src/main/java/androidx/navigation/ui/NavigationUI.kt
ap...@google.com <ap...@google.com> #135
Branch: androidx-main
commit a55cf6688ef4c844adb5718331d367a8ceceefe6
Author: Ian Lake <ilake@google.com>
Date: Mon May 10 13:12:16 2021
Re-enable launchSingleTop in BottomBarNavDemo
When returning to the first item, we still
only want one instance - this is the exact
use case for launchSingleTop.
Test: manual testing of the demo app
BUG: 80029773
Change-Id: If71dfec3986c70e064c28535944118a93c5f7974
M navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/BottomBarNavDemo.kt
il...@google.com <il...@google.com> #136
With these last changes and snapshot build #7351514, we've completed all of the required changes to support multiple back stacks in:
-
Fragments (i.e., without using the Navigation Component at all): this is an opt in change by using the new FragmentManager APIs of
saveBackStack
andrestoreBackStack
. -
The core Navigation Runtime: adds opt-in new
NavOptions
methods forrestoreState
andsaveState
and a new overload ofpopBackStack()
that also accepts asaveState
boolean (defaults to false). -
Navigation with Fragments: the
FragmentNavigator
now utilizes the newNavigator
APIs to properly translate the Navigation Runtime APIs into the Fragment APIs by using the Navigation Runtime APIs. -
NavigationUI
: TheonNavDestinationSelected()
,BottomNavigationView.setupWithNavController()
andNavigationView.setupWithNavController()
now use the newrestoreState
andsaveState
NavOptions
by default whenever they would pop the back stack. This means that every app using thoseNavigationUI
APIs will get multiple back stacks without any code changes on their part after upgrading the Navigation 2.4.0-alpha01. -
Navigation Compose:
NavHost
and theComposeNavigator
have also been updated to support saving and restoring the state by using the Navigation Runtime APIs. An example of using therestoreState
+saveState
APIs with a bottom nav can be seen in the .BottomBarNavDemo
All of these changes will be available in the upcoming Fragment 1.4.0-alpha01 and Navigation 2.4.0-alpha01 releases. (Note that Navigation Compose versioning has been merged into the rest of Navigation as per
That being said:
- there's a lot more documentation and samples that need to be updated. We'll be tackling as much of this as possible between now and the alpha01 release.
- As you may have seen, there's been a huge number of changes needed to make this happen across all levels. As such, please file separate bugs as you discover any edge cases that we need to handle and we'll make sure those changes are addressed in an alpha02 release.
I'd like to thank you for your patience and respectfulness in not spamming this issue with comments.
al...@gmail.com <al...@gmail.com> #137
so...@gmail.com <so...@gmail.com> #138
em...@gmail.com <em...@gmail.com> #139
ga...@gmail.com <ga...@gmail.com> #140
sh...@gmail.com <sh...@gmail.com> #141
ar...@gmail.com <ar...@gmail.com> #142
bo...@gmail.com <bo...@gmail.com> #143
to...@appsfactory.de <to...@appsfactory.de> #144
mi...@gmail.com <mi...@gmail.com> #145
With the new version, how can I navigate to the destination in another graph? Let's say, I would want to navigate from Title to UserProfile screen in the NavigationAdvancedSample app.
Calling navigate() throws an exception "Navigation action/destination xx cannot be found from the current destination". Is it supported by 2.4.0-alpha01 release?
th...@gmail.com <th...@gmail.com> #146
il...@gmail.com <il...@gmail.com> #147
I'm also facing a couple of new issues. The first one is related to a transition crash:
java.lang.IndexOutOfBoundsException: Index: 10, Size: 10
at java.util.ArrayList.get(ArrayList.java:437)
at androidx.fragment.app.FragmentTransitionImpl.setNameOverridesReordered(FragmentTransitionImpl.java:182)
at androidx.fragment.app.DefaultSpecialEffectsController.startTransitions(DefaultSpecialEffectsController.java:665)
at androidx.fragment.app.DefaultSpecialEffectsController.executeOperations(DefaultSpecialEffectsController.java:114)
at androidx.fragment.app.SpecialEffectsController.executePendingOperations(SpecialEffectsController.java:294)
at androidx.fragment.app.Fragment$3.run(Fragment.java:2760)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
MaterialContainerTransform
is used here.
And the second one is related to a significant performance drop. It seems like the app is almost freezing for a fraction of a second on the bottom navigation stacks swap.
br...@gmail.com <br...@gmail.com> #148
java.lang.IllegalArgumentException:
at androidx.fragment.app.FragmentManager.saveBackStackState (FragmentManager.java:2052)
at androidx.fragment.app.FragmentManager$SaveBackStackState.generateOps (FragmentManager.java:3172)
at androidx.fragment.app.FragmentManager.generateOpsForPendingActions (FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions (FragmentManager.java:1643)
at androidx.fragment.app.FragmentManager$4.run (FragmentManager.java:480)
at android.os.Handler.handleCallback (Handler.java:883)
at android.os.Handler.dispatchMessage (Handler.java:100)
at android.os.Looper.loop (Looper.java:241)
at android.app.ActivityThread.main (ActivityThread.java:7617)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:941)
I appreciate the work you guys are putting on this, thanks ;)
il...@google.com <il...@google.com> #149
Please always file a new issue instead of commenting on already marked as Fixed bugs.
mi...@iotashome.com <mi...@iotashome.com> #150
il...@google.com <il...@google.com> #151
Re #150 - no, please always file a new issue. That way each issue can be triaged separately for the appropriate release and deduped against one another.
dh...@bacancy.com <dh...@bacancy.com> #152
lk...@gmail.com <lk...@gmail.com> #153
ph...@gmail.com <ph...@gmail.com> #154
sa...@google.com <sa...@google.com> #155
Re #154: Please file a separate issue so we can more appropriately track your issue.
ph...@gmail.com <ph...@gmail.com> #156
am...@gmail.com <am...@gmail.com> #157
What if I don't want to use popUpTo() and want to keep my bottomNavBar stack growing?
Is it too crazy to ask for a backstack in each destination? - The destination itself will have its own backstack without the need to save/restore. Soon as the destination is visible/active it will query its internal Backstack and present the proper child screen it host. That will make a lot easier to design Apps like Instagram, which is probably the reason why many of us are here.
Description
- scroll position should be maintained between tabs
- pressing the tab again should reset its' backstack and scroll
- pressing back should go back in the current tab's backstack and then exit the app (it should not switch between tabs)
- each tab should have it's own backstack
(I am not sure which parts of this are already implemented, but the scroll/backstack support isn't there)."