I have one Activity with 3 fragments which form a workflow to collect user input.
Normally, Fragment A is the first fragment -> Launches B -> Launches C. B is supposed to launch A if the back button is pressed, and similarly C's Back button is supposed to launch B.
However, in some cases, A is supposed to launch C directly, and then C's back should launch A again.
I prefer that C should not know who launched it. I.e. I want C's "backstack" to operate without C knowing who launched it.
I tried using the usual addToBackstack approach, but I'm facing a problem when the Activity gets killed after the user lets the app go into the background while C was open.
I would like the user to return to "C" instead of starting all over from A. To achieve this I'm using the saved Instance state, and detecting which fragment was previously active, and launching it from the activity.
The problem starts when the user wants to go back from C, after the Activity was recreated after being killed. C doesn't know who launched it: A or B. How do I make the Back button work as expected for this case?
Found some answers in this excellent video by Android Developers + Adam Powell:
Fragments: Google I/O 2016
In summary, Fragments and the Fragment BackStack are considered part of the navigational state of the app, so, as long as I don't mess with the backstack when the activity is launched, the OS will also restore the FragmentBackStack, thus the BackStack will know who launched C (A or B) even if the activity gets re-created. Thus, popBackStack will move from C to A or B as required.
Related
I have an app that has one Activity that loads fragments… on initial startup it loads fragment A. From A the user can navigate to fragment B; and from B navigate to fragment C. Each time a fragment is replaced I do addToBackStack. The back button navigates as one would expect, C to B to A, and if you press back again the app exits.
I’m also using a Dropbox datastore to save all my app’s data so I can move seamlessly between devices and have all my data synced. This seems to be working well. As part of my data I store which fragment was last displayed. Now when my app starts on a second device it correctly displays the most recently opened fragment. This works fine, however, I no longer have a backstack. For example, if the app is showing fragment C device one and then I start the app on device two, as expected fragment C is shown on device two. But when I press the back button, the app exits instead of showing fragment B. (Which makes sense since on device two the app only loaded fragment C.)
So my question: How do I pre-populate my baskstack such that when pressing the back button on device two that it navigates to fragment B?
Check out TaskStackBuilder or the activity XML declaration android:parentActivityName.
I solved this by just committing multiple fragment transactions. Works for me
supportFragmentManager.beginTransaction().replace(R.id.content, Fragment1(), "f1").addToBackStack(null).commit()
supportFragmentManager.beginTransaction().replace(R.id.content, Fragment2(), "f2").addToBackStack(null).commit()
supportFragmentManager.beginTransaction().replace(R.id.content, Fragment3(), "f3").addToBackStack(null).commit()
supportFragmentManager.beginTransaction().replace(R.id.content, Fragment4(), "f4").commit()
However, for a cleaner and better solution you could also have a look at the Jetpack Navigation UI
I'm new to Android development and I have an app with various activities. For performance reasons I'd like to properly manage the activities when users are using my app. Here's my problem.
Activity A - starting activity with map
Activity B - user navigates to Activity B (a list view) from Activity A.
The user then selects the map icon to navigate to Activity A again.
So if you can image it, my activity stack is now:
Activity A
Activity B
Activity A
So if I press the back button the device it will take forever as it scrolls through activities.
Is there a way of managing this so the old activity is destroyed and is just re-created upon choosing an activity nav icon. I've read up about onDestroy() and onStop() but I'm a little confused at their implementation.
Apologies for a poorly worded question but I'm unsure of the correct lexicon to ask about activities.
One simple solution is to kill the Activities as soon as they leave the foreground.
You could do that by calling finish() inside onPause().
You could have B finish itself and return to A instead of starting another A. Or, if your stack might be more complicated, like this:
D
C
B
A
D could start A with FLAG_ACTIVITY_CLEAR_TOP, which would cause D, C, and B to be finished, leaving A on top. (That intent flag interacts non-intuitively with a couple other flags, so read the docs.)
I have a splash activity (A) that calls a listview activity (B) which calls another activity (C).
When I'm on activity C and I press Home, than kill the app (or wait of Android to do it), than longpress Home and come back to activity C there's a strange problem:
When I click back I go back to B. Than I have a backbutton handler that asks the user if they want to exit and calls finish() on the activity. When I try to exit in this scenario, activity A starts again.
On regular operation it finishes B and doesn't go back to A.
Why is that??
Thanks
When the app is killed (either by you or by Android) the process hosting your applications is killed. However, Android remembers the state of the activity stack (in your case A->B->C).
When the user returns to the app, Android creates a new process for the app and recreates only the activity that was at the top of the activity stack (in this case: C). Now the user presses BACK, which causes activity C to finish and Android recreates the instance of activity B which is then shown (You will see calls to B.onCreate(), B.onStart() and B.onResume()).
Now the user presses BACK again. Your back button handler tries to call finish() on activity A, but there is no instance of activity A. Android hasn't created it yet! When activity B finishes Android remembers that there was an instance of activity A in the activity stack underneath B so it recreates the instance of activity A which is then shown (You will see calls to A.onCreate(), A.onStart() and A.onResume()).
I hope this explains what you are seeing.
Make sure you are calling finish() on A when you load B
lets imagine this application like enclosed image. R stands for Root activity and A and B are other activities. A is for displaying of some list, B stands for displaying detail of some value. From R I can get by 4 buttons to 4 A activities. My question is, whether in this scenario is A activity initialized for each time or I would be using only one A activity among whole application. If user selects A in right top corner activity A, then displays detail B and then from detail B goes to another list (but based on A activity). Will he still got the same content from the first A or he can have "new" A activity with another list?
Here is the point - I will be having let's say hundred of activites. Lot of them are "forms" displaying some content, application will have about 50 variants of those forms. Can I make for each form one activity a reuse it again in my activity without having connections to past usage of this activity?
Use android:launchMode="singleInstance" in your manifest if you want a single instance of your activity class
By default activities start over entirely every time you open them with a call to startActivity(). If your activity starts a new activity, it will essentially be put on to an activity stack and is paused while the new activity starts. If the user presses the back button, the last activity on the stack will resume as it left off (though I don't think this is 100% guaranteed as Android will kill off tasks as it needs resources so I wouldn't assume it).
So if you have this chain here:
A->B->C->D
where each letter represents a new activity with absolutely no flags or changes.
If the user is at D and presses the back button, C will resume. D is popped from the stack. If the user decides to go to activity D again, a new D will start as if it didn't happen (assuming you didn't save any persistent variables). If the user presses back twice, the application will be at B where C and D are no gone.
You can manipulate this chain with various flags like singleInstance to keep its state, or noHistory to ensure it doesn't get put to the stack (meaning it will be skipped if the user presses back).
Very detailed description of the various attributes
I'm using a custom Launcher application with Widgets that are used to launch (and provide status updates) for an application.
The application consists of a few Activities - let's call them A, B and C for simplicity.
A is the launched Activity. The user proceeds from A to B and then to C (never in any other order).
At any time the user can press the 'Home' button on the remote control and return to the launcher application.
If the user then presses the 'Back' button on the remote control they always return to the Activity they were last using (A, B, or C).
However, if they click on the widget (rather than pressing back) the Activity that is brought to the front seems inconsistent!
So, here is an example of what happens
From (custom) launcher, use widget to launch application
Activity A appears
User presses a button that launches Activity B
Activity B appears
User presses 'Home'
Launcher appears
From (custom) launcher, use widget to launch application
Activity A appears NOT B
Sometimes I get Activity B instead of Activity A - but I'm not sure under what circumstances. I want to get the Activity at the top of the stack to be displayed and never any other Activity (Activity B in the example above).
I've read Google's documentation about the Activity flags ("single-task", "single-instance", etc...) but nothing seemed to jump out as the solution to my problem.
In my case, Activities A, B, C only make sense when run in that order - and it never makes sense to see a previous activity unless you explicitly go back to it.
I'm not sure if the problem is the way the widget is launching the application or whether there is something I need to specify in my manifest or something else.
Any ideas?
Thanks,
Dan
Isn't that what's supposed to happen? Isn't your widget launching activity A? Would you expect it to launch activity B if you are asking it to launch activity A?
(Althought you say that you get B launched sometimes. Isn't this related to the app being forced out of the memory?)
I'm sorry, but this is not an answer, but rather some additional information related to that same question.
I have found a pattern for Activities when relaunched after home button is pressed.
See my question for all my research:
Android Activity Stack is not working as stated in the docs - last activity in task stack not shown
Hope this can be of help...
I have been reading that the suggested fix for this strange behavior is the use of a "Dispatcher" class as Main that will launch the activity based on the application state...or you can also keep track of all the activities opened that need to be restored...but this can become really cumbersome when having a complex UI application design.