I have been told recently that extending the Application Class in order to use it as a Singleton was a bad practice but without any explanation.
So what are the potentials problem behind the use of this class ? I have seen it used in many projects.
Also, if using the Application Class is a bad idea, what are the alternatives to store application level variables ?
Using a Singleton approach is not really a bad idea, but it may be troublesome in the cases when being used in a multi-threaded environment where one thread sets a value to a variable and the other thread may over-write that value without any notice.
However, in order to keep application level instances/variables, it is suggested to extend Application class and define it in your AndroidManifest.xml as the default one. Since the application's context is created only once (till the application is running and stays in the memory) when you launch that application, so you may define some variables inside that class to make them availabe anywhere in your application's code using public methods.
Moreover, you may use your application class as Singleton too, since its guaranteed to be created only once when launched.
The problem with using a Singleton class, as well as extending the Application class, is that if the application process is killed - which is very likely to happen when the app is left too long in background - the object will lose all your data.
However, using Application class may be a good option in cases when your app is in foreground or does not stay to much in background (although not 100% risk free).
As an alternative, you could save the data into SharedPreferences, or if your object is more complex, save it in a database.
Another option would be to combine both the use of Application, plus SharedPreferences for example. First try to retrieve the variable from Application instance, if the variable is null, then retrieve it from SharedPreferences.
Related
I am working on a solution or code that can be embedded inside of an Android APK to track how many times the app has been launched and how long the app has ran for. I know one way to do this is using the ActivityLifecycleMethods in API 14 and in lower versions of Android having code placed in all Activity Lifecycle events or by providing a base Activity class.
1) Is there a way to hook the ActivityLifecycleMethods without the developer having to make any changes to their code outside of dropping additional code into their App?
I believe this answer is no because even with an Enum Singleton it is not loaded until it is referenced. Also the Enum Singleton will go away once the activity is changed since a different class loader is used when activities change.
If I wanted to keep the Enum Singleton around would it be possible to store a reference to the applicationContext and thus it wouldn't be removed when the Activity changes? Is that what google means by
"There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton." on http://developer.android.com/reference/android/app/Application.html
2) I am not a fan of this solution for older API versions. It seems very likely developers could forget to modify their Activity Lifecycle methods or forget to inherit from the created BaseActivity. Are there any other unique solutions for these older platforms? Is there any other approaches that can be done to determine when an activity isn't running? Could any of the following work:
a) User a class loader to ensure the base activity with the proper metrics are always used
b) Implement some type of heart beat. Will a timer stop working if the app is paused or killed? Is there some other way? Could the ActivityManager be used?
You have many Analytic Agents like Flurry to do that.
When ever you want to track an event, you will add it to flurry and inturn it syncs with server after specific time.
You may use the same logic.
Better create a library file with following features:
Start Application
End Application and report time to db.
Track a specific event count and update to db.
Sync the data to server you like to.
Call appropriate events from your app.
What's the best way to save any changes to global state, that would be lost if the process was killed due to low memory etc?
For activities we have onSaveInstanceState() which allows state to be saved when needed.
I would like something similar for global state. Our Application class holds a references to many objects that can be simply reloaded in onCreate() when the app next starts. But we also change the state of some of those objects, and require these changes to be maintained through the app being killed due to low memory etc.
We could of course persist every time changes are made to the objects in memory. But this would be very wasteful.
My current thought is to use onActivitySaveInstanceState() and keep a dirty flag to know only to call it once. But this adds complexity and probably isn't what this method was intended for.
This cannot be a particularly uncommon requirement, but most of the resources on the net focus on just Activity lifecycle. I'd be pleased to learn of a better approach.
There is no concept of Global State and I actually think that you don't need it at all. An app consists of several independent parts which have their own "state". Thus each part is responsible for its own state. For instance, a fragment which shows particular data knows where to get this data and what to do if there is no such data. An activity which shows user settings knows where to get user settings, how to update it and so on. Both of these parts know what to do when lifecycle methods are calling.
You can always store values in your Application class. On a high level, this is very simple, you create a custom MyCustomApplication, that extends the Android Application class. The Applicaiton class only lives, while the App is in scope (including when it's in the background, which is somewhat unpredictable in Android).
Then you would can access this using the getContext().getApplication()
The implementation details are more complex, and you really should extend the Applicaiton into a Singleton, as described in this SO post: Singletons vs. Application Context in Android?
I am considering using the android Application class as a place to store temporary state and common code shared by other (fragment) activities in the app.
I would like to get more feedback as to whether it is a good place for:
Shared constants like ID's, pref key names, etc.
Global variables (i.e. setters/getters) reflecting current UI state, navigation, selected fragment, and, in general, temporary data that does not need to be persisted.
Hooks for persisting data when certain conditions are triggered.
Updating the UI after preference changes.
Providing an easy way to access the context from anywhere in the app, including code where getApplication() is not available, e.g. via a static getter such as MyApp.getApp().
Common methods that need the visibility of the global state variables and which would become too cumbersome to move away to dedicated classes.
What else would be appropriate/useful/handy to have in the activity class? What would not be a good idea to keep in it and what would be the best alternatives? And finally, what you have found Application to be best used for in your apps?
Shared constants like ID's, pref key names, etc.
I generally create a constants file called C for this, as its better for readability. C.SHARED_PREFS is easier to understand that Application.SHARED_PREFS IMHO.
Global variables (i.e. setters/getters) reflecting current UI state,
navigation, selected fragment, and, in general, temporary data that
does not need to be persisted.
This would be better off in the Activity or component which it concerns (for example, the UI state of an Activity should probably stored in the icicle bundle, or within that instance of the Activity).
Hooks for persisting data when certain conditions are triggered.
This should be fine.
Updating the UI after preference changes.
Again, I feel this would be better off in the respective component.
Providing an easy way to access the context from anywhere in the app,
including code where getApplication() is not available, e.g. via a
static getter such as MyApp.getApp().
This would work, but be careful of memory leaks. You should generally pass the context in as a parameter when calling the method from an Activity or Service or whatever. Less chances of a memory leak.
Common methods that need the visibility of the global state variables
and which would become too cumbersome to move away to dedicated
classes.
I feel it would be better to make the effort of dedicated classes, as when your app grows in features and size, this will become difficult to maintain.
It is probably some place where certain hooks can be attached.
For instance, if you use ACRA crash reporting library, you just need to use the Application class, because this is where ACRA is attached. This is that forced me to start using this class; I never needed the one before.
Just wondering what is a better practice to pass information between activites, adding it to a bundle or using a singleton class to store and access this data. I have used both in the past for various android side projects, but I am now working on an android project that is of much larger scale, so would prefer to do things right towards the beginning.
My application authenticates users and then will have to do various queries based on it's id. To minimize coupling between activities, I would think just adding the id to the bundle, and then letting each activity query for the information that it needs, would be the best bet; however to increase responsiveness, I was leaning towards using a singleton class to store persistent information, preventing more queries than need be.
Personally, I would create an extension of Application to store the state of your app and share data between the different activities. The Application acts as the context for your whole app and Android guarantees there will always only be one instance across your app. Hence it works similar to defining your own Singleton, but using Application will allow Android to take control of the life cycle of your shared data and basically do the memory management for you.
Here are some more details. If you go down this path, you can simply add any getter/setter (or other) method to your application extension to store/retrieve data and do operations on it. Especially the latter can become quite a pain to manage (and keep consistent) when using Bundles passed back and forth between activities. If would only use a Bundle if the data is needed in just one or two places that are neighbours in the activity flow and does not need any (complex) operations to be run on it.
The better way to go for you is to use SharedPreferences to keep userId you need to keep and reuse. Of course you can use singleton approach or even Application class, but the data will be lost after application is killed.
The only time I pass data between Activities via bunlde is if it's something that I won't need to access for a while(i.e the the resID of a resource I want to use only once in the calling activity, etc). I would also think the difference in responsiveness would be very minimal, so that shouldn't be of concern. I suggest the singleton approach
Passing bundles is a tedious job. You'll have to pass a bundle for every change in activity to make sure that the value is not lost, even if you're not using the value in the called activity.
Singleton pattern have some bad results. For example:From Main activity you call secondary activity. Phone call interrupted your work.After ending phone call Android is trying to bring secondary activity to screen. Here is my nightmare - many users complaint about exceptions - Google reported to me NULL pointers in my singleton. So you have to provide not only singleton, but all data inside singleton have to be as singleton too. This maked come very complicated :(
I have an application that is driven by a configuration XML: various
app properties are loaded at the app start-time by parsing the XML and
initializing static variables of some class. The data read from this
XML drives different Activities of the application. Presently, I have
called the "parsing and the properties-initialization" from the
onCreate() of my Main Activity.
I have a few questions as regards this case/approach:
Should I invoke the app initialization method from the Application
Object or is the current approach correct? What advantages/
disadvantages do/would we get/have if I choose to invoke it from the
Application object?
Do we really need a static class to store app properties? Or can we have all the properties as a static Collection variable in the application object?
Parsing a XML(~200 nodes) at app load time might take some time(not
sure how long tho); How can I avoid the dreaded ANRs? I am using a
Pull Parser.
Please help me find answers to these questions.
Thank you.
It depends on what you're initializing. Application's onCreate() should be used when you're doing things that need to be done before any part of your app works correctly and only needs to be done once, whereas Activity/Service/etc's onCreate() should be used for things that are needed for that component alone and needs to be done multiple times.
The main concern I have for putting all your initialization into a component is that it will make extending your application more difficult later on. Suppose you want to make some Activity in your application accessible by outside intents - now you've got to either move the initialization code to Application or you have to duplicate initialization code in the non-launcher Activity.
It sounds like you should check out SharedPreferences, especially PreferenceManager.getDefaultSharedPreferences(). The preferences will be stored between sessions and it gives you easy access to simple properties from any Context.
Threading. I find AsyncTask to be the easiest way to accomplish this task; there's a good write-up on it at Google. Alternatively, you could fire up a Service to do this in the background while having a foreground Activity inform the user that you're booting up the app.
The Application object is used for sharing non-persistent state across the application. I don't think you'll need to use an Application class at all. You can do your initialisation in the onCreate() method of the Activity that is called first. To quote the documentation:
The subclass is optional; most applications won't need one. In the absence of a subclass, Android uses an instance of the base Application class.
You don't need to create your own class to store application properties. This is done for you by SharedPreferences.
You should also have a look at the setDefaultValues() method in the PreferenceManager
class as this will set preferences from the data in an XML file. What's nice about this method is that use the readAgain parameter so that the XML is only parsed once - the first time you start up your application - rather than every time.