When I start my android-activity first onCreate() is called, then onResume().
When I then press the back-button to return to the home-screen and tap the app-icon again, first onCreate() is called, then onResume() and then onDestroy().
My app is still active then, but doing some action result in error since onDestroy() sets a few members to null.
Why is that?
Update: When I wait 30 seconds after pressing back everything works fine. I'm not doing anything heavy in onDestroy except setting a few variables to null and .interrupt()ing a background-thread.
Figured this out by myself. My understanding of what an Activity is was flawed. Of course Android calls onDestroy() on the old Activity instance, which can happen several seconds after the new one has been constructed.
onDestroy gets called because, by default, pressing back key results in your activity calling finish() which initiates the destroying of the activity which calls onDestroy().
To prevent doing some action in case the activity is being destroyed do like this:
if(!isFinishing()) {
// do your action here
}
isFinishing is a method of the Activity.
are you doing some heavy operations in onDestroy(). I think your activity view is destroyed, but not the activity object. And you tap on the App icon even before the previous Activity object is actually destroyed.
I think there is something in addition to what you are describing. Android doesn't just keep activity from being destroyed, something MUST be happening on the main thread.
The symptoms sound exactly as if you had either:
a service doing a longish HTTP or database operation. Are you sure there are no suxg things?
another thread (perhaps managed by an AsyncTask?) calling a synchronized method
Related
I found a bug in our code that we are launching the activity(let's call this as SCREEN_ACTIVITY) by
Intent intent = new Intent(SharedIntents.INTENT_SCREEN);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Android documentation : When using FLAG_ACTIVITY_NEW_TASK, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in.
So everything works fine in most of the case.
That screen activity will call finish() when user click something. Also this screen activity will get launch or create by incoming event from the service.
6053 I/ScreenActivity(15395): onCreate
6682 E/ScreenActivity(15395): finish() Activity
6832 I/ScreenActivity(15395): onDestroy
7284 I/ScreenActivity(15395): onCreate
7911 E/ScreenActivity(15395): finish() Activity
8063 I/ScreenActivity(15395): onDestroy
10555 I/ScreenActivity(15395): onCreate
13413 E/ScreenActivity(15395): finish() Activity
13701 I/ScreenActivity(15395): onCreate
13799 I/ScreenActivity(15395): onDestroy
The last one is the issue. ScreenActivity is created and then call finish() itself. But the problem is that onDestroy is being called very late. Before that there is incoming event from the server and calling startActivity() trigger a new ScreenAcitivty onCreate(). The problem is that ScreenManager class keeps flags for that activity created and destroyed.
The flag is set when onCreate() callback and onDestroy() callback.
So for line 10555 and 13701 the ScreenManager set createFlag = true. for line 13799 set createFlag = false.
The event comes after line 13799 will assume that the activity is not created and events are not notified to the activity.
Hope my description for the issue is clear to you.
Is this kind of scenario onStop() and onDestroy() call so late after calling finish() is expected to happen? If yes, i have to think about the solution.
If not, then is there any places to modify?
Thanks a lot.
onDestroy() may or may not be called. You cannot rely on it being called all the time. From the docs:
Note: do not count on this method being called as a place for saving
data! For example, if an activity is editing data in a content
provider, those edits should be committed in either onPause() or
onSaveInstanceState(Bundle), not here. This method is usually
implemented to free resources like threads that are associated with an
activity, so that a destroyed activity does not leave such things
around while the rest of its application is still running. There are
situations where the system will simply kill the activity's hosting
process without calling this method (or any others) in it, so it
should not be used to do things that are intended to remain around
after the process goes away.
If you need to know that your Activity is finishing, a reliable way to know if it is finishing is the isFinishing() method. You can call it in onPause() to find out if this pause will eventually lead to this Activity being destroyed:
#Override
protected void onPause() {
super.onPause();
if (isFinishing()) {
// Here you can be sure the Activity will be destroyed eventually
}
}
use Handler,
new Handler().postDelayed(new Runnable() {
#Override
public void run()
//enter code here for open an Activity
}
},300);
after that, we are getting log should be:
onCreate
onStop
onDestroy
onCreate
In my code i call finish on a activity but the onDestroy method of this activity not be called. would anyone can tell me why? when the onDestroy method will be called?
onDestroy() is called only when system is low on resources(memory, cpu time and so on) and makes a decision to kill your activity/application or when somebody calls finish() on your activity.
So, to test your code() you can make a test button, that will call finish() on your activity.
I believe you don't need to call all this stuff in onDestroy() until adap is not a critical resource. And even in that case android system has mechanisms to properly dispose them.
For More Details you can Refer Here
In Activity, I register receiver in onCreate and unregister it onDestroy. It should works fine if every onCreate is followed by onDestroy after the next onCreate. Otherwise, if onCreate is being called more than onDestroy, receiver is registered multiple time and the app mis-behaves.
So my questions are:
Is that ok I register receiver in onCreate and unregister it in onDestroy?
Is that onCreate is always followed by onDestroy before next onCreate?
onDestroy is not guaranteed to be called:
http://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29
"
protected void onDestroy ()
Added in API level 1
Perform any final cleanup before an activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
"
You may also want to look at this thread:
Activity OnDestroy never called?
onDestroy is called when the activity is being destroyed. Or removed from the back stack, when ever the user doesn't want it or there is no possible way to get back to it. When your activity wants to receive a broadcast that is fine to do it how you are. If there are no dialogs appearing or notifications or toasts appearing after you receive that should be fine also, if you want to be on the real safe side and only have one activity receiving at a time, and only while the activity is visible move these to onResume and onPause.
You could probably some how unregister when another activity has been brought to the front and re-register after?
Here is the scenario:
I have two Activities. Lets name them Activity A and Activity B.
Say Activity A is open. Now, when I go and open Activity B, Activity A is closed because the onStop() method is called.
Now, when I flip back to Activity A, the onCreate() method is called, but I want the onRestart() method called instead. How do I do this?
You cannot influence the livecycle of your app like that. There should be no reason to rely on onRestart(). If you use onStart() it will always be called no matter if the Android OS killed the app process in the background.
Check out this doc for further information:
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Damn beat me to it but here goes anyway
According to the Activity Lifecycle onCreate() is called again if the Activity was removed from memory because the OS deemed that another app needed the memory. In this case, you can't ensure that onRestart() will always be called for your Activity.
Like already stated you must find a different way of achieving your goal by using the other Lifecycle methods such as onStart() or onResume
I'm not sure if it fits your needs, I had to do an update service that starts the first time I open ActivityA (main Activity) and stops when exiting from ActivityA (not returning back from ActivityB),
I've placed the "start code" in onCreate() when savedInstanceState is null and the "stop code" in onDestroy() if isFinishing() is true
I have an Android activity we'll call A which has a button and another activity B. When the user clicks the button in Activity A, I'd like to finish A (let both onStop and onDestroy finish running) and then start up the instance of B. When I put a finish() and startActivity() call in the button click listener, the instance of B starts up before the old instance of A finishes. Can someone help me figure out a way to do what I'm looking for?
What you are looking for is not possible and actually is against Android's activity lifecycle implementation.
Correction
It is possible with android:noHistory="true" tag in your manifest, but for what you are trying to do it seems wrong (read the EDIT)... Messing with the activity stack makes a non intuitive application!
Android OS doesn't let you control when activities will be removed from memory (or killed), and therefore all these fancy "Task killers" are so popular (DONT use them, they only make things worse).
When your activity's onStop() is being called, the activity stops completely, and it just hangs in your memory, but that's fine...
If you want to reset the state of activity A, or close the app when exiting activity B, just create a set of rules in both onResume() and onStop(), you can do everything you wish by creating a set of rules in those functions.
for example: have a boolean in activity A that turns true just before calling activity B,call finish() on your activity A's if this boolean is true
I suggest that you take a look at Android's Activity lifecycle diagram, and make sure that everything you do follows the best practice.
EDIT
I saw your comment, it seems like you are trying to create things that are already in your memory, don't recreate them, it's a waste of CPU time, memory, and battery.
Instead, create a static class with a singleton that will hold all your shared data !
I believe you're looking for
onPause()
which is what gets called when the activity is sent to the background. You can do whatever cleanup you want in there. onStop should only be called when a user is exiting out of your program (or launching another one)
onPause is a better place to do this cleanup. See the Saving Persistent State section of the Activity doc.
When an activity's onPause() method is called, it should commit to the backing content provider or file any changes the user has made. This ensures that those changes will be seen by any other activity that is about to run. You will probably want to commit your data even more aggressively at key times during your activity's lifecycle: for example before starting a new activity, before finishing your own activity, when the user switches between input fields, etc.
While I'm not definite that your cleanup is for user changes, the bold sentence above implies that onPause will complete before the next Activity is created. Of course that probably implies that you'll have to move some setup to onResume...
Alternatively, you could move all your cleanup code to a method, let's just call it cleanup and then just call it before you start activity B. You'll have to put in appropriate guards for your onDestroy cleanup too of course.
override finish() method.
implement cleanUp() method.
create boolean isClean=false in the activity
in cleanUp() write your clean up code.
call cleanUp() in your finish()
check for isCleaned in finish() or in cleanUp() if its true then ignore the clean
now before you start B , call cleanUp() and set isCleand=true
after you call B , call finish()
Start activity A
from inside A startService(c) and finsh A
from inside the service , start Activity B