One instance of an activity being started with an intent - android

I have an activity that is started from another activity via a button and which gets passed an intent when started.
I now figured out, that the activity is then created several times, since it is started with an intent, and will call onCreate() every time I hit the button mentioned above. In the documentation I read it says "Every time there's a new intent for a "standard" activity, a new instance of the class is created to respond to that intent", so that I assume that I then have several instances of that activity somewhere on the stack. This is what I would like to avoid, since the activity has some static variables which are referenced from other activites and I want to make sure that the value of this variable is deterministic!
What I want is to get rid of all existing instances and create a new instance of the activity when I press the button, or make sure to have just one activity and create it with the new intent everytime.
I tried to achieve this by setting android:launchMode="singleTop" for the activity and implementing onNewIntent(intent). This should make sure that I only have one instance of the activity in this scenario and I get the new intent. However if I do it like this, I basically have to copy my whole onCreate() method, but just using the new intent, which feels wrong.
public void onNewIntent(Intent intent) {
myAdapter= null;
serverThread.stopThread();
serverThread = null;
this.onCreate(...); // <- somehow do all this with new intent
}
Do you have a good idea how to solve this situation easily?

You can move all that code from onCreate() to onStart() to make sure it's called every time that activity is being opened

Try setting the flag FLAG_ACTIVITY_REORDER_TO_FRONT
It will ensure that if an activity exists in the stack, it will bring that activity to the front.
Intent intent = new Intent(getApplicationContext(),
YourCustomActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

In the above situation actually onDestroy() is called when the user is navigating back to the previous activity with the button creating the intent and starting the activity. I.e. actually in this case there is already only one instance of the activity and the previous one is being destroyed.
For this reason onNewIntent() is not called in the above setup. If you want to e.g. stop a server, as indicated above in the question by a piece of code, so that you can start a new one when pressing the button again, you hence can actually simply do this:
#Override
public void onDestroy() {
serverThread.stopThread();
super.onDestroy();
}
Hope that helps others :)

Related

Save Activity Instance And do not create in second Loading

I have a project that has A ListView and some Buttons, and some ArrayList and String.
I fill out the ListView from a DB Query, that takes some seconds to Load, and when its loads,end-user do something and go to next Activity Via StartActivity(myIntent) method.
When goes to next activity, it will be back to this activity and cause it has a DB Query, takes some seconds and even if network got problem, it get force close Message.
How can i save the whole instance of this Activity just once time and again Restore it in second time?
Im new to android, any help will appreciate.
This is my onCreate Method :
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.type_of_dairy);
// all methods, views, initials and ....
}
In case your use-case is that you need to start the first activity from the second activity using startActivity method. You can do the following to bring the existing first activity to front:
Intent intent = new Intent(this, FirstACtivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
//intent. // Your code here
startActivity(intent);
Basically this flag "FLAG_ACTIVITY_REORDER_TO_FRONT" will bring the existing activity to top. So, your onCreate() method will not be called again and your issue will be resolved. In case you want to execute some code when this happens, you can use onNewIntent() method of the activity to handle the new intent and initialize your variables/fields there. Let me know if you have any doubts.

Android: How to get back to the Calling Activity without using finish()

I call an activity called Activity1 from an Activity called MainActivity using the following:
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
So, when the control comes to Activity1. The normal activity lifecycle is started. i.e onCreate() is called and so on.
when i click the back button when the control is in Activity1. The finish method is called, which in turn calls the onDestroy() and now the control is back with the MainActivity screen.
#Override
public void onBackPressed() {
Log.d(TAG, "onBackPressed()");
finish();
}
The next time i call Activity1. The onCreate is called again as i called the onDestroy (when i pressed the back button) from the previous call.
Question:
1. is there a way to pass control back to the MainActivity when the back button is pressed without having to call the "finish()" method?
2. problem with calling finish, every time i call Activity1 from MainActivity, A new instance of Activity1 is created. that is the lifecycle again starts from onCreate()..
i do not want this to happen as this is has become a major performance issue.
The main point i'm looking for is whether i can start the activity1 from the resume state rather than oncreate, when i call it after the first time.
I don't believe you need to call the "finish()" method on onBackPressed. Android does that for you when you press the back button. The onBackPressed is used to last minuet tidy up (save stuff to sharepreferences, etc).
Android default behaviour is to call onCreate whenever a new activity is place on the screen. You cannot call a new Intent without this to happen.
I'm not sure why this is performance issue for you. Can you go in a little more detail what activity1 is doing? Are you doing heavy network communication? Is it possible you can cache the store results?
in Actitity1 you define your WebView as:
private static WebView webView = null;
in onCreate() you only create it if it's null:
if(webView == null){
//create webview and load from network
}
Use this approach wisely as it may easly lead to memory leaks if you point to objects in other activities, or objects that may be kept alive (runnables, messages, etc.)

How to make an activity stop, rather then be destroyed, from the BACK key?

Right now an activity gets destroyed when the BACK key is pressed. How can I make it just stop ( i.e. keep all the variables, etc. alive ), rather then be destroyed?
Thanks!
Why is it that you need to keep the variables alive? Given the established lifecycle of an Android application, I'm not sure that preventing the activity from being destroyed "just to keep the variables" makes sense.
Even if you stop the application without destroying it, there is always the chance that Android will kill it to free up memory. You will have to account for this in your code anyway, and so preventing the application from destroying doesn't save you from writing code.
Variables can be saved and restored relatively easily and quickly using SharedPreferences in your onPause() and onResume() methods. Unless you are storing a ton of data, preventing the application from destroying might not make much of a difference.
It sounds like you want to keep the variables in memory because you intend to return to this activity. Typically, you don't use the back button to navigate away from activities that you intend to come back to. Instead you would create an Intent and start a new activity. When you do this, Android places the current activity on the Back Stack calling onPause() and onStop(), which seems like exactly the sort of behavior you are looking for.
So if you still really want to prevent your activity from being destroyed (at least until Android decides it's using too much memory and kills it on it's own) you could always use Sagar's code and start a new activity in onBackPressed().
#Override
public void onBackPressed()
{
Intent intent = new Intent(this, Other.class);
startActivity(intent);
}
Just be certain that that is what you really want to do.
Simple one line
#Override
public void onBackPressed() {
mActivity.moveTaskToBack(true);
}
Pressing the BACK key triggers the onBackPressed callback method of Activity class. The default implementation of this callback calls the finish() method.
http://developer.android.com/reference/android/app/Activity.html#onBackPressed()
You can override this method to move the activity to background (mimick the action of pressing the HOME key.
eg:
#Override
public void onBackPressed() {
onKeyDown(KeyEvent.KEYCODE_HOME);
}
You could also instead consider moveTaskToBackground() mentioned here:
Override back button to act like home button
I have managed to work out exactly what you want: switch between 2 activities using Back button and keep them all not to be destroyed!
For example: you have 2 activities A & B. A will be started first, then A calls B. When B is loaded, user press Back button and switches back to activity A from B. From now B should not be destroyed and just goes to background, and when user starts activity B from A again, activity B will be brought to foreground, instead of being re-created again or created new instance! How to implement this:
1. Override onBackPressed() of activity B:
#Override
public void onBackPressed() {
Intent backIntent = new Intent(this, ActivityA.class);
backIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(backIntent);
}
2. On activity A, call activity B:
public void callActivityB() {
Intent toBintent = new Intent(this, ActivityB.class);
toBIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(toBintent);
}
remember to add flag: Intent.FLAG_ACTIVITY_REORDER_TO_FRONT when you call A&B.
This is similar to this question that was asked earlier.
Hope this helps!
N.S.
First of all, sorry for not answering the question, cause, I still have no optimal answer for it.
But, I really like when people start asking "what do you need this for". And, very rarely, the person who asked the question, really deserves this kind of question. I think not this time, but ok, this is not the issue...
Anyway, I will try to point out why some of us are convinced that
going from Activity A to Activity B(creating UI based on some data fetching) AND
going back from B to A(destroying all the created UI and/or fetched data in B) is sometimes a bad concept. Better solution would be to keep the stack as it is, so using something like finish() in Activity B, but keeping the Activity B in Pause state, so later when calling it again from Activity A - it just goes in onResume = nothing recreated in UI, no additional data fetching. The bonus of course is a fast and responsive UI, and the difference is really if you have a more complicated UI layout.
Just specify in the manifest for the activity as
android:persistent="true"
That should prevent your activity getting destroyed. To know more about this please refer to these below links which were answered by me
How to prevent call of onDestroy() after onPause()?
Prevent activity from being destroyed as long as possible
In the above posts I have explained in detail with a use case

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.

Start new activity from notification in android

I want to start a Activity A from status bar notification, When the activity A is already in front then i want to finish that and fresh start activity A. How can i do this?
Review the documentation on creating Status Bar Notifications. This definitely covers starting and Activity from a Notification using an Intent and PendingIntent.
http://developer.android.com/guide/topics/ui/notifiers/notifications.html
As for if the Activity is already running, finish it and start it freshly... I'm not sure that can be done easily, depending on what you really want. You may be able to do something with the launch mode activity parameter in the manifest:
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
And then have your activity respond (with onNewIntent() most likely) and "reset" itself programmatically. Possibly with something like this:
Android restart my activity
You mean re-start Activity A? While the most common approach is just to re-launch a new Intent with your same class I think it uses way too memory. I'd rather create an "init" method which should be called from the onCreate AND when you want to re-launch your activity. Example:
public void onCreate(Bundle si){
// Call super and set your layout...
init();
}
/**
* This method should be called whenever you want to restart your activity. The
* biggest advantage is you already have your layout (setContentView() method)
*/
private void relaunchActivityA(){
// Clean or save anything you need to clean or save
init();
}
private void init(){
// Init your variables, threads, and so on
}
If you wrote 'finish that and fresh start Activity A' instead of 'Activity B', then right after your startActivity() -on activity A- call 'finish'. Example:
// This is inside Activity A
Intent i = new Intent(this, ActivityB.class);
startActivity();
finish(); // This will be called right after 'Activity B' finishes

Categories

Resources