Let's say we develop an app with web authorisation. We need some "global" service to determine whether the user is logged. If user is logged, the service must provide some data (such as cookies, auth token, etc) to identity user, otherwise the service must have a way to set this data.
There are couple of ways of doing it. We can use static context (singleton or just static fields) to store this data. We also may create some Service to get all this data from.
But what way is recommended by Google? What way is ideologically correct? Perhaps there are other ways to implement that?
Don't know what's recommended by Google but if you need an object that lives as long as your application lives then it would be the Application object.
So subclass your own MyApplication extends Application, define whatever fields you need in there and then declare MyApplication in manifest and access by (MyApplication)getApplication()
Create manager (singleton pattern) that describes your app model. Yes, make sure also that it does not hold context of Activity, Service and etc. If need context, make sure to call getApplicationContext().
Singelton is the simplest way doing it (+design pattern)
But from time to time, there may be problems using singeltons: if the application process is killed, which will happen almost undoubtedly if you leave the app in the background too long, your singleton will be recreated, and so your private int data will be reset to a default value.
Maybe if you don't want to use too much shared data you can use sharedpreferences to avoid this.
Else you could try Extending the Application class.
Hope helps
Related
I'm using IntentServices to call a restful service and then turn over the result to a receiver. The back-end requires a user id and authentication token, which I stored in a singleton class. I've run into issues with this singleton being cleaned up when the process is terminated, and its data isn't around when Android tries to restart my activities. User preferences seem like a great place to start this kind of data, but those require a reference to your context.
Where can I put this data so it can be accessed outside of the view? I realize I could just pass it with every single Intent that triggers my IntentService, but am hoping there's a better way.
Thanks!
Service is a ContextWrapper which is a Context so you can use the keyword this when getting an instance of your shared prefs.
For lightweight data such as a few strings etc, SharedPreferences is fine. Just pass any context, every component has one or is one itself. Or pass the application context. Lack of context shouldn't be an issue. Pass it along into your singleton as a parameter.
Using a database, or inventing a proprietary storage mechanism using a file, or creating a content provider, all seem overkill to me.
If you don't want to pass it all the time (which is not that bad), and you still want to stay in the Android framework philosophy, create a ContentProvider for this task.
Or you can go full classical and save them in some file. Or in a sqlite database (Android offers easy support for this).
I've been rereading this and can't make a sense of it, could you, probably explain it to me?
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.
From http://developer.android.com/reference/android/app/Application.html
I fail to see why there's no need to subclass Application. I often subclass it so I can access application context from everywhere. So, what shall be the proper way according to this document?
I think the idea is to avoid overloading the Application class but instead having multiple small singleton classes focused on different concerns.
That's probably what they mean by "more modular way".
Normally people make the "Application" class so that they can store objects in it to persist the entire lifetime of the app or transfer between activities. I think what that line is saying that simply making it static would achieve the same purpose, in a more "modular" way.
As for application context, did you already know about getApplicationContext()?
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've got a quick question on the best way to handle Android contexts. A lot of things (e.g. Service) require that you pass a context as a parameter. At the present time, I have a public static variable that is set to point to getApplication() and I just refer to this throughout my application where a context is required.
Is this ok to do? Or is there a better method to handle this? A lot of my classes don't extend Activity or service and as such, don't have access to this.getApplication().
Everything seems to work ok when I just pass in my static variable.
Is this ok to do?
The Application object, in some cases, will fail to work. For example, it sucks for UI-related stuff.
Dianne Hackborn, a leading Android engineer, has stated her regret at Application existing in the first place.
My general advice is to use Application only when you know specifically why it is superior to using your Activity, Service, etc. There are cases when it is the better answer (e.g., binding to services).
A lot of my classes don't extend Activity or service and as such, dont have access to this.getApplication().
Pass a suitable Context as a parameter, as the Android SDK does.
At the present time, I have a public static variable that is set to
point to getApplication() and I just refer to this throughout my
application where a context is required.
Is this ok to do?
No.
A context applies to the context in which it was obtained. That is, an activity has context for that activity, a service has context for the service, and so on. Now, a lot of folks do what you are doing, and as you observe, it seems to work. That doesn't mean it will continue to work or that it's good design. If that was the proper pattern, Android would have been designed with Context.INSTANCE that is available statically.
An activity, service, and application are contexts (isA). Receivers are passed a context to their onHandlerIntent() method. For all other classes you write, just get used to constructing them with a context. Out of habit, whenever I create a new class, I automatically add a constructor that accepts a context and add a private field to hold it.
When you need a context in a static method, you should pass it in directly as a parameter.
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.