We write different activity classes in Android and declare those activities in AndroidManifest.xml
However, what I am not getting is when is the object of that Activity class created or how that activity class is loaded into memory ?
The doubt might seem naive but am confused.
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View). The activity contains the user interface of your application. There are various states of activity like Running, Paused, Stopped and Killed. The Activity base class contains several events that govern the life cycle of an activity.
Now, when Activities's onDestroy method is called, your Activities aren't necessarily garbage collected. When the system gets low on memory the process that your Application lives in can be killed, meaning your Application will disappear; Application's onTerminate method may or may not be called. At that time all the Activities, Services, etc, are killed too. The Application instance is always instantiated first, an Activity must have an associated Application, just like how you define it in the AndroidManifest.xml.
As always, the best resource for understanding all this is the official documentation.
An Activity is instantiated automatically by your Application when it receives an Intent that corresponds with one of the Activities you describe in your manifest. You don't need to worry about any constructor methods, or keeping a reference to your activity after its instantiated. That is done behind the scenes. Android handles the lifecycle, so you use the lifecycle callbacks to handle creation and cleanup of your own objects.
When someone clicks the icon for your app in the launcher, what actually happens is the launcher sends an Intent to your application to launch the activity associated with that Intent. If your application isn't open yet, Android will launch it so it can receive the Intent.
Related
I am trying to use a static singleton DataManager that makes network requests and holds arrays of data for my Activity, instantiated in my Activity's onCreate() class, but the idea that the Activity gets destroyed every time there is an orientation change is tripping me up. I don't want to re-create a new singleton and re-populate it with data every time the user changes the orientation or comes back to the screen.
Even if I make DataManager a Service, if I make it a Bound Service, it seems like the Service will get destroyed whenever my Activity gets destroyed, but if I don't make it a bound service and use startService() and stopService() in my Activity, it also gets destroyed whenever my Activity is destroyed.
Also, if I use onSaveInstanceState() and onRestoreInstanceState() to save my instance of the singleton, it possible that my singleton would get destroyed when my Activity is inactive, since there is no longer a pointer to it. Then Activity B using the same DataManager class could create another DataManager instance while Activity A is inactive. Then Activity A wakes up, inflating another Data Manager, giving us 2 DataManagers that are no longer singletons and may have inconsistent data.
I have read elsewhere that I should not subclass Application to maintain app state, but I don't understand how it would work any other way. Thanks for any clarification.
Subclass the application class and then instantiation your singleton within the application.onCreate() callback. This way it will be available for the lifetime of your application rather than the lifetime of a single activity. Careful that this won't be garbage collected until someone kills your app so don't have too many "Global" singletons.
DO NOT do the work in Application.onCreate(). You will be slowing down your application start up, no matter what happens. This is not advised for Android applications, you want your app to start promptly.
Instead, if you really need a singleton, have it construct lazily when it's necessary.(If you are sure you will use it, you you can also force the construction asynchronously from a separate thread when your activity starts). When your activity gets destroyed, it doesn't mean the whole process will be immediately torn down, so your singleton will stay alive.
Also, if you are using a singleton, make sure to be able to clear it when memory is low. You will need to implement Application.onTrimMemory(int) and clear the singleton from there.
In the Android Application class you can register/unregister ActivityLifecycleCallbacks, which allow you to monitor Activity lifecycle events in your application all in one place (if you so desire).
Where is the proper place to call unregisterActivityLifecycleCallbacks? I'm registering in onCreate, and was thinking that onTerminate would be the proper place just from the name of the method but the docs say for onTerminate():
This method is for use in emulated process environments. It will never
be called on a production Android device, where processes are removed
by simply killing them; no user code (including this callback) is
executed when doing so.
I don't see any other methods in the Application class where a 'shutdown' type callback is made. Do you even need to unregister?
Simon was right about this. registerActivityLifecycleCallbacks doesn't require a matching call to unregisterActivityLifecycleCallbacks. As described in this SO question you can't detected when your application is being killed. So there is no "logical" place to unregister your callback. And even if there was, your Application instance is killed after the last Activity action takes place, and the killing of your Application kills the mActivityLifecycleCallbacks list which holds the reference to your callback anyway.
TL;DR - Don't worry about calling unregisterActivityLifecycleCallbacks, it's only there if you want to stop tracking Activity actions during your Application's normal lifecycle.
I've got a complex application: an Application class and a bunch of Activity classes started as Intents from a common Activity.
According to the logs, the process is dying. It happens when I run my app, hit home, start up a whole bunch of other apps and then return to my app.
In the log, I see:
10-25 12:11:08.195: I/ActivityManager(2492): Process my.awesome.app (pid 20860) has died.
my.awesome.app then goes thru the onCreate() method of the main Activity as the app restarts.
However, I end up at the wrong screen because the instance variable that would direct me to the correct screen is not retaining the value it had when the app died. Actually, I'm hoping the app didn't die so much as it was killed by the system and then brought back to life.
Looking at the code, I see no onSaveInstanceState()/onRestoreInstanceState() methods so I'm pretty sure I need to provide them.
The question is which Activities need to provide onSaveInstanceState()/onRestoreInstanceState()/react to what they've done?
Let's say I'm a couple of Activities deep - that is, my Application class has started an Activity class that started a Thread to run an Activity and itself is running another Activity via an Intent.
Do all the involved classes need to provide/react to onSaveInstanceState()/onRestoreInstanceState()? Is it just the Application class since that's where I'm detecting the improper value that sends me to the wrong screen?
onSave/onRestoreInstanceState isn't really for application wide settings. It's more for settings particular to a single activity.
If you always want to go back to a certain activity after a process has been killed, you should probably save the last open state into a preference, and then in onCreate of your main launcher activity, launch the desired activity based on the value of the saved preference.
This doesn't appear to be well documented or I missed it, so before I run a bunch of my own tests I was wondering if anyone already knows the answers to some of these questions.
First off, when I say "Application" I am referring to extending the Application class. http://developer.android.com/reference/android/app/Application.html
The questions I have are as follows, some are related.
When an a user leaves an Activity from within the Application, and goes to the Activity of another application, does the Application somehow get paused as well, even though it doesn't have an onPause()? Or does it continue to live unpaused until all of it's activities are destroyed?
when does the Application stop? When all of it's Activities are destroyed?
Is there ever a chance that one of the Applications Activities could be running without an instance of the Application, or will the Application class always exist if one of the Activities does?
If there is some process running on the Application, and it's Activities are all paused, will that process continue to run?
Is the Application effected by rotation in any way or does rotation only change Activities?
Thanks
As you say the application does not have onPause so nothing happens to the application. When onPause gets called in your Activity nothing special happens, your Activity continues to run and can do whatever it wants including run new threads, timers can go off, whatever.
I believe what you are asking is: when is an Application destroyed and when the onTerminate method in an Application called? The answer is hard to pinpoint and is up to the system, it does not necessarily happen when all activities get onDestroyed called. In fact even when onDestroy is called, your Activities aren't necessarily garbage collected. When the system gets low on memory the process that your Application lives in can be killed, meaning your Application will disappear; onTerminate may or may not be called. At that time all the Activities, Services, etc, are killed too.
The Application is always instantiated first, an Activity must have an associated Application, just like how you define it in the AndroidManifest.xml.
Processes never pause in Android, the onPause method does not actually really do anything other than tell you to pause things in your app. Other than that the process keeps chugging away, your threads keep running, even the main thread receive Intents with a BroadcastReceiver.
The Application gets rotation callbacks in the Application's onConfigurationChanged(). I'm not sure if you can disable that since there is no configChanges attributes supported by application tags in the AndroidManifest.xml.
A good comparison to Application is static field in any of your classes. The static fields will live as long the process is not destroyed, just like the Application. Static fields can be accessed by all Activities, Services, etc (assume the static fields are public), just like your Application.
Good Luck!
Jacob
The easiest way to understand this is to just forget that Application exists. Application has nothing to do with the application lifecycle. It is just a global on a process, that can be useful for some things, but is not needed for anything. Everything about how an application runs revolves around the Activity, BroadcastReceiver, Service, and ContentProvider components declared in its .apk.
An instance of Application can continue to exist after your last Activity is destroyed. Even if ALL activities are gone (ie. have all had their onDestroy methods called), the Application instance could still exist.
This application instance could be "re-used" for what you might otherwise think are two separate runs of your application.
This is all explained in detail here: http://developer.android.com/reference/android/app/Activity.html. If you read through it, you should understand everything.
Real quick:
Every activity has an onPause. You can choose not to override it, but it'll get called nonetheless. As soon as you switch away, onPause will be called.
Define "stop". Define "Application". The process may linger around forever, but it'll simply sleep and wait until one of its activities is started.
It's impossible for an activity to exist without being instantiated.
Every code executed runs in a process, so there's always one process for your app. The process will continue to exist after you switch to a different app, but it'll be in sleeping state. Android could at any time kill the process if system resources run low.
Every time you rotate the screen, your activity will be destroyed and recreated, unless you specifically disable that.
I have an android app. I added an intent filter to one of my activities, so that if a url is clicked in the browser app, my activity can be launched. Looks like this:
<data android:host="www.mysite.com" android:scheme="http"></data>
this works well. The problem is that every time my activity is launched from the browser, a new instance of the activity is created, inside the browser app's task, instead of recycling any existing instance that may be in the system already.
This is a problem for me because this activity uses a singleton. If I allow more than one instance of this activity to exist, I can get into some weird situations where the two instances are in conflict when they try to share the singleton. I checked and can see that although the activity instances may be in separate tasks, they do share the same singleton instance.
An ideal solution for me would be if I could somehow bring a pre-existing instance of my application to the foreground, and launch or resume the target activity within whatever pre-existing instance of my app happens to be running.
So I tried this:
Register above filter to point to dummy activity which is just a catcher.
Dummy activity creates a broadcast intent, and tries to broadcast 'create me' message to system.
Real target activity is set to listen for this broadcast message. Hopefully if there is already an instance of the activity in the system, it will come to the foreground. If no instance yet, that's ok, allow creation in the browser task.
Not sure if this makes sense. My basic goal is to limit the activity to one instance in the system. The app is just social media app which has a login state that needs to be preserved. The singleton mentioned above preserves that login state, so I want to have only one around in the system, instead of allowing multiple login instances running around which would be a headache for the user.
Thanks
You can set the activity launch mode to singleTop to achieve this.
android:launchMode
An instruction on how the activity should be launched. There are four modes that work in conjunction with activity flags (FLAG_ACTIVITY_* constants) in Intent objects to determine what should happen when the activity is called upon to handle an intent. They are:
"standard"
"singleTop"
"singleTask"
"singleInstance"
The default mode is "standard".
https://developer.android.com/guide/topics/manifest/activity-element.html#lmode