I have an app that starts a sequence of dialog-themed activities and I want to be able to pop them all off at once and go back to the main activity. I looked over existing questions like:
How to clear current activities in the stack?
how to kill sub activities and bring activity to top of stack
Android Popping off the Activity Stack
And based on that came up with this:
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
This works functionally, but the problem I have is that when this is executed, the screen behind the dialog-themed activity turns black for a second before finally animating the dialogs off the screen. If I pop these activities manually with a back button this does not happen.
In LogCat I can see that when I pop the dialogs using the Intent method above, the main activity is destroyed and re-created, whereas when I just use the back button, the onDestroy and onCreate methods do not run. Is there any way to prevent the main activity from being explicitly re-started this way?
You could just add singleTop to your main activity.
Here, read about it. It brings the existing instance of the activity rather than create a new one.
http://developer.android.com/guide/topics/manifest/activity-element.html
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_SINGLE_TOP
What about if you, when you add your main activity to the backstack you add it with a tag other than null like:
transaction.addToBackStack("welcome");
And then you can just pop the backstack like such:
FragmentManager fm = getFragmentManager();
fm.popBackStack("welcome", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Related
I've read in the android docs that singleTop mode is this:
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 activity at the top of the back stack is
not an existing instance of the activity).
However, my app is behaving differently. My main activity has the singleTop launch mode defined in the manifest file. Here is where it's behaving oddly.
Start main activity from launcher.
From main activity, start sub activity.
When user presses back button (or actionbar home button), it sends intent to main activity with some extras. This means that main activity needs to be updated (depending on the user actions in sub activity.)
Main activity is shown with updated display.
-- the odd part is this --
From main activity, pressing back button goes back again to main activity.
Pressing back button a 2nd time brings up the launcher screen, then my app is put in the background.
On step 5, why does it bring up the main activity again? I thought singleTop will bring to front the main activity which is the current top of the stack in the task. But from that behavior in #5 and #6, it seems like it's creating two instances of main activity instead.
Is my understanding incorrect or something else is going on that I'm not clear of yet. Please help explain/clarify. Thanks.
My sub activity has its onBackPressed method overridden. And likewise, the main activity onNewIntent() handles the extras.
#Override
public void onBackPressed() {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(MainActivity.UPDATE_ARG, true);
startActivity(intent);
super.onBackPressed();
}
Note: If I use singleTask mode, it behaves as I expected of singleTop. But I've read somewhere that singleTask and singleInstance are to be used sparingly.
From posted doc:
one task can have multiple instances (but only if the activity at the
top of the back stack is not an existing instance of the activity).
From your code:
When user presses back button (or actionbar home button), it sends
intent to main activity with some extras. This means that main
activity needs to be updated (depending on the user actions in sub
activity.)
when user presses back button your main activity dose not exist at the top of the current task and your sub activity is at the top because it has not destroyed yet, so it creates another main activity and do not use existing one because that main activity is not top.
look at this from the doc, note that the backstack contains current foreground activity:
why does it bring up the main activity again?
Well, because you're starting your activity again when you do:
startActivity(intent);
Any updates in your Activity should be performed in the onStart method (or onResume if applicable).
I've finally made sense out of all this (I think!). I'll explain.
android:launchMode attribute applies to the activity whether it's started from home launcher, from within your app (or from another app).
The intent flag Intent.FLAG_ACTIVITY_CLEAR_TOP is needed to implement the singleTop behavior. Therefore, I passed that flag when creating the intent prior to starting the activity.
For the main activity, here's what I did:
#Override
public void onBackPressed() {
Intent intent = new Intent(this, MainActivity.class);
// these flags are important!!
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(MainActivity.UPDATE_ARG, true);
startActivity(intent);
super.onBackPressed();
}
And correspondingly, I declared android:launchMode="singleTop" in the manifest file.
Here is my situation:
I have MAIN activity, four TOOLBAR activities, that user can launch from always visible toolbar and other activites.
What I want:
App start with MAIN Activity. Then user goes to Main -> TOOLBARActivity (1) - OtherActivity(1) - OtherActivity(2) - ... - TOOLBARActivity(2).
When launching the TOOLBARActivity(2) I need to clear all stack from Main till TOOLBARActivity(2). So if now user will press the back button, he will return to MAIN Activity.
So, I simply need find the way to clear all activities in stack except the first one.
When you go to your second Activity you can use like this :
intent = new Intent(this,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
StartActivity(intent);
this flag clears top of Activity stack
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
I am new in android and I have total 6-7 activities in my application. I want to know how can I manage my activities properly means when I move to the A->B->C->D like that. Then how can I move that the stack of these activities not created.
On moving from one activity to the other I am using the below code:
Intent intent=new Intent(current.this,next.class);
startActivityForResult(intent, 0);
And now if I want to move back on the earlier activity I used the code as:
Intent start = new Intent(current.this,next.class);
startActivity(start);
finishActivity(0);
Is there a special reason that you don't want to use the activity stack and let the activities handle themselves?
The Android system has done a very good job with the activity lifecycle. It allows you to start an Activity from different places without confusing the user because the back button will bring the user back to a different activity.
If you don't have a very good reason to not use the Android guideline try to stick to the way the system is doing it. Every other thing will only give you problems.
You are starting activities for a result but how I understand you you will never return to them.
You can start an Activity and after that just finish the current Activity. That way the activity will not be put on the back stack. Now you need to listen for back button pushes and create the activities that you want to bring the user to.
If you want to move from Activity A to D like going to the start/home screen of you app you do the following:
Intent goBackToA = new Intent(context, StdActivity.class);
goBackToA.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(goBackToA);
The flag FLAG_ACTIVITY_CLEAR_TOP will tell the system that if the backstack contains an instance of the Activity this activity will be shown and all activity that are between the current activity and the target activity are removed from the backstack. This allows you to go back to a home activity without creating huge loops that the user can move through with the back button.
To move back to the previous activity you don't have to create a new intent, you can simply call this.finish() on the one that should dissapear.
To move back to the previous activity you don't have to create a new intent, you can simply call this.finish() on the one that should dissapeear or you can press Back button to see the previous Activity .
whenever you want to navigate from one class to another use this code, may be this help you to navigate the Activity,
Intent nextpage = new Intent(CurrentActivity.this,NextActivity.class);
startActivity(nextpage);
this.finish();
I'm building an app that requires a user to have logged in and obtained a user id. This id is a member variable of my extended Application class.
I'd like the application to recognize when/if this variable gets wiped out and, if so, throw up my log in screen and destroy the Activity stack behind it.
Here's what I think I'm going to do:
Extend Activity and ListActivity (currently the only two types of Activities I am using). In the onResume() handler, check to see if the user id is set. If not, throw up the log in screen and destroy the rest of the Activity stack behind it. All of my Activities will derive from these new extended Activities.
My issue here is that I don't know how to destroy the Activity stack behind a particular Activity. Any ideas?
One idea is to have a broadcast receive listening for a particular message that tells Activities to kill themselves, but I'm hoping Android already has something in place for a situation like this.
Update:
Also, is there a way to clear the entire Activity stack? I'd like to override the onBackPressed() handler on an Activity and have the Activity stack blown out so the user gets taken back to the Android home screen.
Other choice will be using the noHistory parameter in the AndroidManifest.xml to accomplish this.
so your Activity should not be placed in the history stack
<activity android:name=".MyActivity"
android:noHistory="true" />
I agree with danh32, setting the FLAG_ACTIVITY_CLEAR_TOP on the intent to bring the Login Activity on top of the stack will destroy all activities behind the new activity (hence, the Login Activity). This will leave one activity on the stack.
Intent myIntent = new Intent(view.getContext(), DisplayMenu.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(myIntent);
finish();
I use this option to allow users to get back to a main screen from a long path through a lot of activities.