Long story short: I am currently working on a small android game. One feature is being able to change the app theme. When the user changes the theme, an event is broadcasted throughout the app and all active activities call recreate() to apply the new theme.
The problem:
Let's say there is a stack of activities: A, B, C. All activities will receive the event in the order they were opened and call recreate(). These are the lifecycle events that will get called (in order):
Activity A will call onDestroy(), onCreate(), onStart(), onResume() and onPause()
Activity B will call onDestroy(), onCreate(), onStart(), onResume() and onPause()
Activity C will call onPause(), onStop(), onDestroy(), onCreate(), onStart(), onResume().
Note that neither activity A or B called onStop(). When those activities are being returned to (eg. back button press), they will not call onStart() when they become visible, but will call onResume(). This is contrary to what is stated in the activity lifecycle documentation.
The question: Is there something I'm doing wrong here? Is there another way to restart all activities in an application without messing up the activity lifecycle?
I think you are taking the wrong approach here. You should not use the framework calls in order to change your theme. The issue you are having is that you are not calling onStop as the framework would, but even so...
The primary reason your approach is incorrect is that Android may have already destroyed an Activity if it is not visible. So sending events to it that call framework methods is not only unnecessary at that point, but it could result in unpredictable states and behavior. Could even cause a crash.
For changes to your theme or any UI component, you should handle that in onResume - in other words handle changes to the UI elements when the user returns to the Activity. One option for doing this is passing flags through startActivityForResult.
Better, make your theme selection persist using sharedPreferences (or using another method) and then read from that when the Activity is resumed. This would ensure the proper theme is selected regardless of how the user gets to the Activity.
EDIT:
Note that the Activity framework methods are public not because they should be accessed at any time or by other classes, but because that is required for them to be implemented in your app. They are not intended to be invoked outside the framework.
You should note that in the official documentation for Activity none of the methods you are calling are listed as "Public Methods" (http://developer.android.com/reference/android/app/Activity.html#Activity()). You are using them in an unsupported way. However, I only point this out to make you aware of it and that it is not a generally accepted approach to solving this problem.
This is exactly in line with the documentation.
http://developer.android.com/training/basics/activity-lifecycle/starting.html
If you look at the chart, onResume gets called when returning to an activity no matter what but onStart doesn't.
if you want to change UI related component then you must use OnResume method instead of recreating all activities. like following.
#override
onResume()
{
textview.setText("Change text When activity resumes");
}
Colleagues above responded very well.
The behavior you reported. The onstart and onResume not be called. I've watched it happening to Hot Code Swapping. It is worth stopping the application and call the rebuild.
Related
I have an application with multiple activities and have some behavior in onPause on my MainActivity that I don't want to happen when switching to another activity.
Right now whenever I switch activities the MainActivity onPause() is called and it always runs the behavior.
Activity lifecycles are tightly coordinated, so when launching one Activity B, from Activity A, the following lifecycle events will take place: ActivityA.onPause, ActivityB.onCreate, ActivityB.onStart, ActivityB.onResume, ActivityA.onStop. You can definitely leverage this lifecycle coordination to achieve what you want, if you are move you "behavoir" to the lifecycle method onStop (which is a better place to do most shutdown/stopping work at).
Create a Lifecycle registrar object that will perform the "behavior" when there are no activities are registered in the Lifecycle registrar object. Register your Activities inside of their onStart() and onStop() liefycle callbacks. Inside of the deregister method of your Lifecycle registration object check to see if there are any registered objects and if their aren't you perform you "behavior" whatever that may be. You can extend this functionality to work with Services, just register and deregister the service with the Lifecycle registrar inside the Service's onCreate, onDestroy respectively.
Using onStop instead of onPause, has the added benefit of keeping you from doing your paused/stopped "behavior" when the app is actually in the background and not just partially visibly, such as the case when the system displays a dialog. For example, when requesting to start Bluetooth, the Android OS will generate a dialog prompting the user, and calling onPause. This makes since for some apps but not all apps, and when you think about it, there are a various other use-cases that will cause the app to enter onPause(), that would be annoying to the user for you app to perform shutdown processes.
I have personally utilized this scheme to maintain a open connection, while the app is open and close the connection when the app is killed, or placed in the background. I even modified the Lifecycle Registrar object to maintain the connection during device rotation.
Here's a solution (a little dirty), you can use a boolean to know when you're switching the activity, set it to true just before you call startActivity(intent), and set it to false in onResume().
P.S, using onStop() is better than onPause() in your case, i believe you don't want to delete those cookies when the activity is partially visible
I try to make Notification which must work only when Application UI isn't visible.
I tried to store preference which was written in onStart() and onStop() of my Activity. But sometimes, it's not working because another application became visible without MyActivity.onStop() being called.
What other method I can use for a Service to determine, if MyApplication is visible now? Or, maybe MyActivity?
If you already have code to keep track of the state of your app's UI, you can probably get it to work simply by putting the code in onPause() and onResume(), instead of onStart() and onStop().
It is possible for the UI not to be visible, or partially hidden, even before onStop() gets called ... as you found out.
Take a look at the Android Activity lifecycle diagram here:
http://developer.android.com/images/activity_lifecycle.png
and note the description:
The foreground lifetime of an activity happens between a call to
onResume() until a corresponding call to onPause(). During this time
the activity is in front of all other activities and interacting with
the user. An activity can frequently go between the resumed and paused
states -- for example when the device goes to sleep, when an activity
result is delivered, when a new intent is delivered -- so the code in
these methods should be fairly lightweight.
Read more about this in another question here.
I've read several posts that describe the difference between onStart() and onResume(): onStart() is called when the activity becomes visible, onResume() is called when the activity is ready for interaction from the user. fine.
I've always just added code to onPause() and onResume(), and never bothered with onStart() and onStop().
Can anyone give some concrete examples of what you might do in onStart(), vs. onResume()? Same goes for onStop() and onPause(), how is onStop() useful? I must be missing something fundamental here.
onStop() will (for example) be called when you leave the activity for some other activity (edit: almost. see commonswares comment about dialog themed activities).
For example if you use startActivity() in activity A to start activity B. When you press back in activity B you will return to activity A and onStart will be called.
This differs from some of the reasons onPause might be called without onStop being called. If for example the screen times out or you press the standy button onPause will be called, but probably not onStop (depending on memory available and whatnot), so it is a "lighter pause". onStop will be probably be called eventually even in this case, but not immediately.
Ok, but what's the use
Often there is no specific use, but there might be. Since your activities will keep its memory state on the stack even after you start some other activity, that stack will increase with the number of activities started (height of the stack).
This can lead to large memory usage in some applications. After a while the framework will kick in and kill some activities on the stack, but this is rather blunt and will probably mean a lot of states to be retained when returning.
So an example use for onStart/onStop is if you want to release some state when leaving an activity for another and recreate it when you get back.
I have used it to set listadapters to null, empty image caches and similar (in very specific applications). If you want to free the memory used by visible views in a listadapter you can recreate it in onstart and let the views be picked up by the gc. This will increase the likelyhood that the rest of the memory state of the activity will live on.
Some resources can be deemed good enough to save while the activity instance is alive and some only when it is on the front of the stack. It is up to you to decide what is best in your application and the granularity of create/start/resume gives you that.
onStart() works after onCreate() ended its task.
It's a good place to put a broadcastReceiver or initialize some state about the UI that should display consistently anytime the user comes back to this activity.
onResume() works when you come back to your Intent or Activity by pressing the back button. So onPause will be called every time a different activity comes to the foreground.
i think that your question is pretty explained here on the doc : read about the Activity Life Cycle
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
According to the android Activity Lifecycle, the only callback guaranteed to be called (if an activity ever leaves the Running state, which is typically expected) is onPause().
So, I must assume that there are scenarios in which it makes sense to implement onStop() and onDestroy() although they are not really guaranteed to be called.
I understand that onStop() should be implemented when it's possible for an activity to return to the Running state via the Stopped state (why would it do that instead of returning directly is a different question).
But the need for onDestroy(), when I can place all cleanup/state-saving into onPause(), is unclear to me.
Can you describe a real-app situation (i.e. not analogy to driving a car etc.) in which it would make sense to implement onDestroy()?
onDestroy will be called if you explicitly call finish(); yourself.
Your main activity calls startActivityForResult on a map activity.
Map activity with a LocationListener, the user clicks the map and selects say a local restaurant.
The activity then , sets up some extras to be sent back to your main activity, it then explicitly call's finish(); on itself and in the onDestroy kills the LocationListener and other variables you had invoked.
Just found this in the docs
onDestroy() = The final call you receive before your 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.
Can you describe a real-app situation
(i.e. not analogy to driving a car
etc.) in which it would make sense to
implement onDestroy()?
When you want to capture a configuration change. It's all in the SDK:
http://developer.android.com/reference/android/app/Activity.html