What happens when new activity is started? - android

I'm calling an Intent from an activity: I want to know what happens with the activity when I'm calling the Intent, I mean, is it destroyed? onPause? onStop?
This is what I use to call an Intent:
Intent intent = new Intent(context,class);
context.startActivity(intent);
I want to know that if I have a checkbox in an activity, so for example I check that checkbox and after I go to the next activity, but if I go back to the previous activity, the checkbox is not checked as it was when I call the Intent.
I don't know if I have explained my self, but I hope you can give me a hint to solve this.

By default, the activity is stopped, not destroyed. It might be destroyed if the system is low on resources.
So what's probably happening in your case is, the system gets low on resource so it destroys your activity. You should save your UI state in onSaveInstaceState, and restore it in onRestoreInstanceState. Read more here.

intent.putExtra("",""); Save chackbox state here

Put state of checkbox in shared preferences or static variable and once you go back to that activity , check for its state and populate it if that is the case

I mean, is it destroyed? onPause? onStop?
onStop is called.
From developer.android.com
onStop() - Called when the activity is no longer visible to the user.
Try saving the state of checkbox in static boolean with isChecked() and check that boolean in onRestart() - this is called, when you come back to your previous activity.

There are numerous prior questions on saving the state of a checkbox (whether due to intent or screen rotation). The same generate approach applies:
For instance:
How can I maintain the state of a CheckBox even after navigating to different activities in android?
And to determine the lifecycle calls being made, one can always override the methods with a call to super class and use breakpoints in the debugger. That has always been helpful to me to see the code in motion alongside the Android lifecycle diagrams.

Related

OnCreate method is always called

I read the Android documentation and I don't understand one step:
When I press a button my app shows the Activity2 with the startActivity(intent) method, then I use the back button and my app shows the Activity1 again. If I want show the Activity2 I press the button again, and my app always call onCreate to the Activity2.
The Android documentation says the method onCreate is called only when is starting or when is destroyed.
Why is this happening?
Thanks!!
Regars.
The OnCreate() method is called each time the activity is displayed (created). So each time you call the startActivity(intent) method, the OnCreate method will be called.
Check the Activity Lifecycle for more information.
It's because you pressed the back button when you were in Activity2, which by default destroys the activity you're currently on. You can override onDestroy() and print a debug message to confirm (make sure to call super).
Instead of retaining the same Activity2 object, you should leverage onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle) to save and restore your Activity2's state, respectively.
Technically you could use the Bundle object passed into onCreate(Bundle) as they are the same object. The docs recommend onRestoreInstanceState(Bundle):
Most implementations will simply use onCreate(Bundle) to restore their state, but it is sometimes convenient to do it here after all of the initialization has been done or to allow subclasses to decide whether to use your default implementation.
It's completely normal beheviour. You are calling startActivity() so activity is starting. That's all. This method is called also when you are changing configuration - i.e rotating the device. Moreover - it's also possible that Activity1.onCreate() will be called after pressing back button, while it's going background and can be disposed by system if more ram is needed.

abnormal behavior of parent activity after finishing child activity

I have Activity A and I am calling Activity B from Activity A using setResultForActivity.
Now in Activity B when I press Done button I am firing finish() and it returns to
Activity A and it return down to onActivityResult. Now the issue is after when I fired finish() in Activity B , Activity A's onCreate doesn't get called and thats why
some of the custom listeners in my ListView isn't working , it seems that they are not bind.
so the whole activity respond pretty weirdly , can anyone has solution to this ?
Why a fourth answer? Because in my view, the others aren't fully correct.
Truth is, Activity A could have been destroyed in the meantime, or not. This depends on whether Android needs memory or not. So it is possible that Activity A´s onCreate() is called (along with the other lifecycle callbacks), or not. In the latter case, onActivityResult() is called before onResume().
While for configuration changes, the most efficient way to preserve the Activity's state is via nonConfigurationState, if you want to prepare for a restart of your Activity after it has been destroyed, you can use the InstanceState mechanism, because while Android destroys your Activity A, it will keep its intent and saved instance state to re-crearte it.
This stresses the absolute necessity to place initialization exactly in the callback where it belongs.
To test whether your Activity logic works regardless of whether Android destroyed it or not, you can use the DevTools setting "Development Settings" -> "Immediately destroy activities". The DevTools app is available on AVDs and can also be downloaded from Google Play.
Just place your onCreate() stuff in onResume() of Activity A except setContentView().
Just have a read on Android Activity Lifecycle : http://developer.android.com/training/basics/activity-lifecycle/stopping.html. onCreate() is only called when the activity is first created. You can do your list thing in the onResume() method.
Activity A's onCreate won't get called because the activity has not been destroyed. When an Activity regains focus from another activity, it's onStart and onResume get called, so I would put your bound listeners in those. They will also be called when onCreate is normally called.
After your child activity is finished() it return to execute onActivityResult which is in your case in Activity A. The onCreate method is not supposed and does not get called when killing of you sub-activity, a.k.a Activity B.
Please post some source code for us to work on and I will improve my answer! :)

Setting flag in onSaveInstanceState() to determine exit type in onDestroy()

For online games, it would be great to know if an Android Activity's onDestroy() is only called because Android is going to re-create it (e.g. device rotation) or if the user opted to exit the game.
My plan was to set a flag in the Activity's onSaveInstanceState() when Android is probably re-creating the Activity:
private boolean mDestroyedForReCreation;
...
protected void onSaveInstanceState() {
...
mDestroyedForReCreation = true;
}
If you did this, you can check mDestroyedForReCreation in onDestroy():
If the flag is set (true), don't dismiss the user from the online game.
If the flag is not set (false), dismiss the user from the online game as he did voluntarily exit the game.
Is that a correct approach? And if yes, is it recommended or is there any better solution? I hope so because I don't really like that solution ...
I suggest you to remove such kind of game logic from activity's life cycle. Create a Service. If no one binded - all activities are dead. Is someone binded - keep working.
If you do not want to create service, you can use onRetainNonConfigurationInstance method. Here is example.
You should use onRetainNonConfigurationInstance because it is called by the system, as part of destroying an activity due to a configuration change, when it is known that a new instance will immediately be created for the new configuration. onSaveInstanceState called when android going to kill activity and maybe restore it sometimes or maybe not ).
You can simply avoid restarts on rotation by handling this configuration changes by code. You can do this in your Manifest.xml like this:
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboard|keyboardHidden"
android:label="#string/app_name" >
So your app won't restart on rotation and if the keyboard opened/closed.
I think this solution is much simpler.
In this case you almost don't need to handle onSaveInstanceState() for exiting, except you start another intent/activity where you need to save your game state. Note that a phone call will also interrupt your code. I know some games with funny bugs where the time is resetted but not the score.
I would just simplify the whole thing, and set a flag that is toggled when the user exits the game, something like:
void exitGame() {
mUserExited = true;
finish();
}
(Or you might need more logic if you need to destroy multiple activities)
Then check the flag in onDestroy().
Whatever logic you have about configuration changes (rotation, etc.) will have nothing to do with the exit game flag.
Also, remember that the 'back' button's default behavior is to finish() the current activity (if nothing else is above it) - that won't count as an "exit" in this case. The behavior here is up to you.
Activity has a method called isFinishing() that is probably what you are looking for.
See: https://stackoverflow.com/a/9621078/445348
If you need to know this, you should consider handling rotation and other configuration changed events yourself rather than letting the system do it. If you set in your manifest that the activity handles configChanges, it will call onConfigChange when it rotates rather than destroying and recreating the activity. A large amount of apps do this, the whol destroying and recreating on rotation thing Android does is absolutely retarded.
onRestoreInstanceState() will be called if when it is restored /recreated , if the activity if killed by android it saves its activity UI state and some values you can override onSaveInstanceState
but because onSaveInstanceState() is not guaranteed to be called, you should use it only to record the transient state of the activity (the state of the UI)—you should never use it to store persistent data. Instead, you should use onPause() to store persistent data (such as data that should be saved to a database) when the user leaves the activity. Also onRestart will be called after onStop() when the current activity is being re-displayed to the user. So probably you can save your state in onPause / if onRestart is called it is like it is being re displayed , while if onCreate is called without onRestart it is recreated . Other solution is to use singleInstance and override method onNewIntent which is called if activity is not destructed but like restarted on a new intent .

Pausing/Resuming Activity outside of an activity

I have 2 activities. Main Activity A & Activity B
I do not want Activity A to destroy. I am starting Activity B in a new task.
public static void startActivity(Class<?> startClass) {
Intent intent = new Intent(Constants.getActivity(), startClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Constants.getActivity().startActivity(intent);
}`
Constants.getActivity() returns the Context on current activity
startClass is the either activity "A" or activity "B"
Thing is they create/destroy the activities and they leak. Am I doing it wrong? How can I start activity "B" from activity "A" and vice versa keep them both in background when I dont need them.
First of all, what are you trying to do? You should always separate things you want to do in the background from your UI. Think of your Activities are simply a container to show the UI, everything else can be stored and restored from persistent storage or savedinstance bundles.
It is very crucial that you understand the difference between Activity lifecycle and Service lifecycle here.
I'm going to refer to my answer from another question here:
Your app will be in the background, onResume and onPause will both be called, provided that the OS have enough memory to keep the new app and all the old apps.
If you have a long running process that you need while the user not looking at it, use a service.
If you need the user to return the app in the same state, you need to do the work in onResume and onPause to save the state information and initialize your UI again when the user comes back. If you are really worried that it can get killed (well, it shouldn't lose the bundle I think), you can store them in SharePreferences for your app.
If you want to know when the app returns from that specific share intent, use startActivityForResult
You cannot keep an activity "alive" as you said. When an activity is paused, Android system is always able to claim its memory and unload it, at any time.
But if you want to switch from A to B, then maybe A and B can be different views inside a single activity. Maybe you'll want to have a look at http://developer.android.com/reference/android/widget/ViewFlipper.html
When you use tasks, cleanup is very important. You need to cleanup all tasks in the activity. readthis
If the activity does not have a lot of crazy initialization, just use finish and onCreates. Else be aware that onResume will be called often as you switch between activity's. Cleanup will be crucial here. If you dont cleanup, its possible one of your activities (with dead object reference from the other cleaned up activity) may come back up from the activity stack and throw exceptions. Its very difficult to debug this kinda exception.

Want to start a new activity but let the original activity finish first

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

Categories

Resources