I was going through Android Task and Back Stack documentation and at one point they mention this:
if your application allows users to start a particular activity from more than one activity, a new instance of that activity is created and pushed onto the stack (rather than bringing any previous instance of the activity to the top). As such, one activity in your application might be instantiated multiple times (even from different tasks), as shown in figure 3. As such, if the user navigates backward using the Back button, each instance of the activity is revealed in the order they were opened (each with their own UI state)
Let's take an example:
I have Activity A Starting Activity B which Starts Activity C which starts D.
Stack is A->B->C->D now it is possible to Start C from D so when we start C from D stack will be
A->B->C->D->C
Now instead of this standard behavior I want Activity to have only 1 instance or only 1 entry in the Back Stack. "SingleTop" will not work since Activity C was not on top when we started it from D.
I might be missing something but is there any way to achieve this making sure an activity has only 1 backstack entry?
Thanks
Pranay
Use Intent.FLAG_ACTIVITY_CLEAR_TOP, e.g.:
Intent intent = new Intent(context, <your_activity_here>);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
So, all the activities in stack after activity C will be finished automatically. If you use the specified flag
A->B->C->D
will become
A->B->C
You can also use android:launchMode="singleInstance" in your activity tag in manifest
Related
I am having two activities, Activity A and activity B.
Activity A starts activity B.
So, the activity stack after some interactions will look like A -> B -> A -> B.
The problem:
I need to go the first activity A in the stack from activity B (last B in the stack). I am using FLAG_CLEAR_TOP as well as Intent.FLAG_ACTIVITY_NEW_TASK for achieving the same.
Right now, the activity A (stack pos 3) will be shown from activity B, but when I press back button, the activity B will be shown again (since activity B (stack pos 2) is already there in the stack).
How do I overcome this issue?
PS: I tried using launchMode singleInstance and singleTask for activities A and B, but that solution doesn't work for my app.
Thanks in advance.
Add finish (); after switching activites like
Intent intent = new Intent (activity_a.this, activity_b.class);
startActivity(intent);
finish ();
Avoid creating multiple instances of activities if possible. Android isn't designed to allow you to identify (and return to) a specific instance of an Activity in the stack, if you have multiple instances of the same Activity in the stack.
Depending on your application, there are different ways to solve the problem.
One way that may work for you is to use <activity-alias>, which allows you to reuse an existing Activity implementation by another name.
Another way would be to create another Activity class, that just inherits from the original, so that you have 2 classes with exactly the same code, but with different names.
The best way is to rearchitect your application so that you only ever have one instance of each Activity alive at any given time. You can do this by rearranging the task stack using Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.
Could someone please explain what FLAG_ACTIVITY_SINGLE_TOP do? The docs say
If set, the activity will not be launched if it is already running at
the top of the history stack.
But that statement seems to be burying a great deal of meaning beneath it. For instance someone online mentioned that the top activity may not be the same as the activity at the top of the task stack. I have no idea what all of that means. Hence my greater question: what are the implications of using FLAG_ACTIVITY_SINGLE_TOP?
It means if the activity is already up and you call it again you wont replace it with a new one and you wont create another one (which sometimes happens and is evident when you hit back and you see the same activity up), instead you will pull that one up.
So say you have 3 activities: A -> b -> c. You are in C and you came to it through A and then B. If you call to A, from C with the SINGLE_TOP filter your stack will look like A, C, B - if you started to hit the back button, you would go to C, then B. I could be wrong but thats how i believe it is. You can also pass in the CLEAR filter with it to erase the back stack and techniquely be started back at A with no stack in back of it, you would back straight out to home. - please correct if im inaccurate.
The following is an answer I read online. It is not a complete answer to the question you are asking, so I am really hoping someone else can add a lot more meat to it.
If an instance of the activity already exists at the top of the
current task, the system routes the intent to that instance through a
call to its onNewIntent() method, rather than creating a new instance
of the activity. The activity can be instantiated multiple times, each
instance can belong to different tasks, and one task can have multiple
instances (but only if the the activity at the top of the back stack
is not an existing instance of the activity).
For example, suppose a task's back stack consists of root activity A
with activities B, C, and D on top (the stack is A-B-C-D; D is on
top). An intent arrives for an activity of type D. If D has the
default "standard" launch mode, a new instance of the class is
launched and the stack becomes A-B-C-D-D. However, if D's launch mode
is "singleTop", the existing instance of D is deliverd the intent
through onNewIntent(), because it's at the top of the stack: the
stack remains A-B-C-D. However, if an intent arrives for an activity
of type B, then a new instance of B is added to the stack, even if its
launch mode is "singleTop".
Source
Imagine you have the following sequence of activities:
Activity A -> Activity B -> Activity C
When you are on Activity C, pressing the native back button, takes you to Activity B. Now what is the state of Activity C? Is it still in memory or it has been finished?
If it is still in the memory, is there a way to resume the activity? Other than starting another instance of this activity...
I should add that this is the standard case where you do not use any flags including: FLAG_ACTIVITY_CLEAR_TOP
Default behavior is that when you press hardware "back" button, current activity will be removed from the backstack and activity "destroy" sequence will be initiated. From that moment you should not rely on the fact that it might be somewhere around - it is all up to Android to decide when does it actually kill this activity.
What my previous investigations show is that victim's onDestroy() will be called only when new activity is done loading and is idle.
You can specify android:launchMode="singleInstance" for your activity in Manifest. This will ensure that only one instance of activity is created at the time
You might want to consider reading the official docs.
More specifically the part that answers your question:
When the user presses the Back button, the current activity is popped from the top of the stack (the activity is destroyed) and the previous activity resumes (the previous state of its UI is restored).
Now for your second question… you can keep reading the same page…
when you start an activity, you want to bring forward an existing instance of it (instead of creating a new instance on top of the back stack)
So if you read that… you will find…
You can do these things and more, with attributes in the
manifest element and with flags in the intent that you pass to
startActivity().
In this regard, the principal attributes you can use are:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
And the principal intent flags you can use are:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
No, it is not in memory. It gets finished when you press the back button. You should use android:launchMode="singleTask" in the androidmanifest.xml for that particular activity for which you want no new instances to be created if an instance is already there. For further information this link will be helpful.
In the following sequence...
Activity A -> Activity B -> Activity C
When you will press back button in Activity C then onBackPressed() method will be called. The default behavior of onBackPressed() is to finish the current activity until you Override the functionality.
So, in normal case, after back press the current Activity will be destroyed and you can't find it in the Activity Stack, so you can't resume it.
You will find more information from Android Developer's doc in below link...
Tasks and Back Stack
In intent I can set such flag as FLAG_ACTIVITY_SINGLE_TOP. Can somebody explain me its meaning, cause I just don't get it? =)
The tasks page says for single top:
If an instance of the activity already exists at the top of the current task, the system routes the intent to that instance through a call to its onNewIntent() method, rather than creating a new instance of the activity. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances (but only if the the activity at the top of the back stack is not an existing instance of the activity).
For example, suppose a task's back
stack consists of root activity A with
activities B, C, and D on top (the
stack is A-B-C-D; D is on top). An
intent arrives for an activity of type
D. If D has the default "standard"
launch mode, a new instance of the
class is launched and the stack
becomes A-B-C-D-D. However, if D's
launch mode is "singleTop", the
existing instance of D is deliverd the
intent through onNewIntent(), because
it's at the top of the stack—the stack
remains A-B-C-D. However, if an intent
arrives for an activity of type B,
then a new instance of B is added to
the stack, even if its launch mode is
"singleTop".
Javadoc says:
If set, the activity will not be launched if it is already running at the top of
the history stack.
In my application you can navigate through several Activities until the Activity stack is quite deep.
We'd like a button on every Activity that will take you straight back to the main menu - i.e. pop all Activities from the stack except the first one.
I've put the button in a View that I can easily put on every Activity in the application, but I can't figure out how to close several Activities in one fell swoop.
(If possible, it would be good if the View could work out how many Activities to close by itself - i.e. detect how deep on the stack its own Activity is.)
Have a look at the intent flag FLAG_ACTIVITY_CLEAR_TOP which says it brings the targeted activity to the top of the stack, removing everything else that might have been above it. So use that button you can add to all your activities to launch an intent which targets your main menu, with that flag set.
From the documentation:
If set, and the activity being
launched is already running in the
current task, then instead of
launching a new instance of that
activity, all of the other activities
on top of it will be closed and this
Intent will be delivered to the (now
on top) old activity as a new Intent.
For example, consider a task
consisting of the activities: A, B, C,
D. If D calls startActivity() with an
Intent that resolves to the component
of activity B, then C and D will be
finished and B receive the given
Intent, resulting in the stack now
being: A, B.
The currently running instance of
activity B in the above example will
either receive the new intent you are
starting here in its onNewIntent()
method, or be itself finished and
restarted with the new intent. If it
has declared its launch mode to be
"multiple" (the default) and you have
not set FLAG_ACTIVITY_SINGLE_TOP in
the same intent, then it will be
finished and re-created; for all other
launch modes or if
FLAG_ACTIVITY_SINGLE_TOP is set then
this Intent will be delivered to the
current instance's onNewIntent().
This launch mode can also be used to
good effect in conjunction with
FLAG_ACTIVITY_NEW_TASK: if used to
start the root activity of a task, it
will bring any currently running
instance of that task to the
foreground, and then clear it to its
root state. This is especially useful,
for example, when launching an
activity from the notification
manager.
You could declare that first activity android:launchMode="singleTask" (more) and then just start it with an Intent.
EDIT: My suggestion is based on the assumption that you want to have a single instance of the Activity to return to. Otherwise it's incorrect.