What happens if startActivity() is called to the already created Activity? - android

I want to start my MainActivity with a new Intent in my other Activity. The two Activities are in the same app, and the second Activity is actually started from the MainActivity. So the scenario is like this:
MainActivity is created with an Intent
MainActivity starts SecondActivity (but MainActivity is not destroyed yet. It is just stopped)
SecondActivity starts MainActivity with a new Intent (SecondActivity is not closed)
The MainActivity is not flagged. I mean, the Activity's launch mode in the manifest is not set (so, it's default).
I want to know what happens to MainActivity's lifecycle and intent.
Is the Activity re-created? Is onCreate() called? Then is onCreate() called twice, without onDestory()? Or the new MainActivity is newly created and there will be two MainActivities? Will the Intent from getIntent() overwritten?
I know Activity.onNewIntent() is called for singleTop Activities. Then in my situation onNewIntent() is not called?
Thanks in advance.

Is the Activity re-created? Is onCreate() called? Then is onCreate()
called twice,
Yes, yes, and yes, because the default launchMode of an activity is "standard". Activity with standard launchmode will create a new instance how many times you want.
Will the Intent from getIntent() overwritten?
AFAIK, It's still the same Intent.

If you call startActivity() for an Activity with default launch mode(i.e, you didn't mention any launch mode in either in manifest or in Intent) a new instance of the activity is created.
For example, A launched B and again B launched A then Activity stack would be A - B - A. Pressing back key at this point would take you to B then A.
Your can refer to Tasks and BackStack documentation from Android.

Related

send intent to an already running activity

Main Activity has started activity A and A has started activity B, which is currently visible on the screen: Main Activity -> A -> B.
Now Main Activity receives a broadcast intent and it needs to pass new information from it via A to B without restarting A or B, i.e., the state of A and B should remain as is. For example, if user has written someting to EditText in B, that text should not be lost.
Question: what Intent flags should be used when MainActivity sends intent containing the new information to A and A to B in order to achieve the above described behavior?
Use the activity.startActivity(Intent) method in your Activity B to call activity A ‘s “newIntent(Intent)” method, do with what you need to then :) and maybe make sure in the manifest file the activity is set to SingleInstance
Rather than figthing with intents and launch modes, I decided to save the necessary state of A and B at their onPause() method to a companion object of MainActivity and then restore the state from there at onResume() method of A and B.

Keep only one instance of each activity in entire app

I want to keep a single instance of every Activity I start in my application. The launchMode singleTask was an option but it is working for only one Activity.
I want
to start an Activity if there is no instance and it is called.
and if any other instance of that Activity is present already then
that instance will brought to front without creating a new instance
of that Activity.
This property will be applied to more than one Activity.
No Activity does guarantee that it will be always on the top of the history stack.
My work until now:
I got many suggestions which are not valid for my case, so I want to point these out so that no other person would give the same suggestion.
I have set the launchMode to singleTop and this works only if the Activity is at the top of the history stack. onNewIntent() only gets called if Activity is at the top of history stack. and in my case the Activity may be at any position in stack. So this is not working.
When you launch an Activity, do it like this:
Intent intent = new Intent(this, MyActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
If an instance of this Activity already exists, then it will be moved to the front. If an instance does NOT exist, a new instance will be created.
You can set the android:launchMode of your activity to singleTop
In this case the if the activity already exists, new intents will bring it to front will be delivered to the activity's onNewIntent()
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
This will work if your activity is on the top of the stack.
if you want to have a single instance of the activity, then you can set your launchMode to singleTask, but this is not recommended as it will make your activity reside in a separate task , which can be confusing to the users.
Use singleTop launch mode instead (docs): if there already is an Activity instance with the same type at the top of stack in the caller Task, there would not be any new Activity created, instead an Intent will be sent to an existed Activity instance through onNewIntent() method.
See can also this article for details on launch modes.

Why a "home" activity will be killed when the home button is pressed?

I have created an activity , set it's filter as a Home activity and set launchMode with singleTask. When I press home ,the activity will be in onpause state then onStop . What confuse me is why the activity will be re-launched when back from icon displayed on "home pick" dialog ? It calls onCreate() again without invoked onDestroy().
I know there is a way to solve this problem that is to set launcherMode as singleIstance, but this way is not good enough, because it will cause an other issue that the activity will not be able to process onActivityResult.
You may want to tell what you wish to achieve. Because that's how singleTask is. It delivers existing intent to onNewIntent() of the existing instance of activity. So activity will not be destroyed but onCreate() will be called, as it will reCreate activity with existing intent.
Quoting the documentation
The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.

OnCreate instead of OnResume/OnRestart?

I have some Activities, let's say Activity A, B and C.
In the Activity A I call the B through a Menu with an onOptionsItemSelected:
Intent main = new Intent (this, MainActivity.class);
this.startActivity(main);
Now, when I'm in the B activity, I can call the A one back in the same way (with Intent and startactivity): how can i handle it to call the OnResume or the OnRestart method of A instead of the OnCreate one?
I'm logging it and anytime I move from an activity to another one, it always call the OnCreate method: what can I do?
Configure your Activity A as "singleTask" or "singleInstance" in the manifest.xml. Then Acitivity A's onResume() will be fire instead of onCreate() when you call Activity A from Activity B (assuming Activity A was already instantiated like you describe). There are drawbacks to this kind of configuration so read this.
example manifest:
<activity android:name=".YourActivityA"
android:configChanges="keyboardHidden|orientation"
android:launchMode="singleTask">
You cannot control whether the OnCreate/OnResume/OnRestart methods are called directly. It is based on whether the previous activity is still in memory or not.
http://developer.android.com/guide/components/activities.html
http://developer.android.com/images/activity_lifecycle.png
I'm logging it and anytime I move from an activity to another one, it always call the OnCreate method: what can I do?
To return to Activity A from Activity B, if you use:
startActivity(), then A's onCreate() will always be called.
finish(), then A's onCreate() may or may not be called. (It depends on whether A was destroyed by you or the OS.)

Issue with activity called with Intent.FLAG_ACTIVITY_CLEAR_TOP

I want to finish my app calling the first activity with Intent.FLAG_ACTIVITY_CLEAR_TOP and finishing it. However, when it finishes, the app restarts automatically, and goes directly to Activity 2.
Why? Isn't the stack of activity supposed to be empty after finishing an activity called with Intent.FLAG_ACTIVITY_CLEAR_TOP?
My stack is Activity2>(more activities)>Activity1.
In Activity2
Intent exit_intent=new Intent(context, Activity1.class);
exit_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
exit_intent.putExtra("EXIT", true);
context.startActivity(exit_intent);
In Activity1
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
From the javadoc:
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.
CLEAR_TOP will wipe out all Activities ABOVE Activity1: if Activity2 is below Activity1 then once Activity1 finishes you will see Activity2.
Are you sure finish() is being called properly in Activity1? I'm getting the feeling it's not, because:
I'm not sure where that if statement goes inside your Activity. It should be in onNewIntent.
If you are making that if statement inside the onNewIntent method, it's still wrong. The docs specify that getIntent() will always return the original intent that started the Activity, unless you call setIntent().
To conclude, maybe something else is getting called in your Activity1 (can't tell without the full code) that starts Activity2 instead of finishing.
If what I described is not the case, and your activity stack indeed looks like Activity2 > Activity1 like the others have described yes, it will not work. Just call finish() in Activity2?
According to the docs:
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.
So it doesn't clear the entire activity stack, only any other activities that were on top of an old instance of the activity being launched.
You have it right but are you catching the intent inside onNewIntent method of your first activity? also activity 2 should be launched after activity 1 in order for this to work.
From Intent doc:
public static final int FLAG_ACTIVITY_CLEAR_TOP
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.

Categories

Resources