Is there any reason not to use the Application class to share variables across Activities?
For instance a handle to the DB or a single HttpClient.
According to the official documentation "you can use it to maintain global application state". IMO you wouldn't want to hold onto to too many heavy objects, globally. Ofcourse, "too many" is too fuzzy:) There are other ways of sharing (persistent) data: Preferences, database, files. You might want to check whether any of these are a better fit for your problem.
The other thing that you need to understand about when using Application object is its Life cycle. Unfortunately, discussion of that can be very subjective but fortunately, such as discussion has already been done
Good luck!
The Application object is meant for maintaining Application state rather than resources. Personally, I would initiate DB connections or HTTP clients in each Activity that needs them rather than globally in an Application object.
I don't think there's a huge overhead for creating such objects and it means that when an Activity is stopped those resources can be freed up. If you create them in the Application object they will always be instantiated, using up memory, even if the current Activity doesn't need them.
Related
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 new to android development and I see that there are different components (activities, services, etc.) where each component has a different life cycle.
I am encountering a situation where I have an object that should be accessed by different components. Namely, I have a list of objects that changes dynamically, and that list should be accessed by:
An activity that displays the list in a ListView
A broadcast receiver, that responds to alarm events scheduled in the AlarmManager.
The broadcast receiver may kick in hours after the activity was used. At this time, the activity may or may not be still alive in memory.
Is there anywhere I can put the list so it will be accessible to all app parts? My idea was to serialize the objects I need to share, write them to shared preferences and then recreate them whenever needed. I'm not sure it's a good idea, and even if it is - how would I design it? when would writing to shared preferences (or somewhere else) occur? when would reading occur (it would be preferable to read the object from memory when possible)?
You can put it in SharedPreferences if it a compatible data type, or serialize the list to a file in the internal or external storage (see saving files, you probably want internal storage for your situation).
You can read the list in the onResume() method of the Activity or the onReceive() method of the receiver. Writing will occur whenever a new element needs to be added to the list, you will deserialize the list, add the element and re-serialize it. You may need to place the reading and writing in a synchronized block or method to prevent simultaneous access.
If the list may be added to outside of the Activity when the Activity is resumed you may need to provide a broadcast receiver or other mechanism for the Activity to be alterted and reload the list.
As Gabe pointed out, you could store it in a static variable somewhere, but the way you described the situation serializing sounds like a better option. Otherwise the list is gone if your process is terminated by the Android system.
As kcoppock pointed out, you could use an SQLite database to store the data, but this sounds like overkill from what you described. You will be in for some additional coding without much benefit.
What you are looking for is the Android Shared Preferences. You can access Sharepreferences using getApplicationContext() from an Activity or a Service.
Hope this helps
If you don't want it permanently stored, put it in a static variable somewhere (anywhere they both agree to- a separate class would be a good idea). Then you can access the list unless Android kicks the class out of memory- which it should only do it its terminating the app due to lack of memory, in which case it doesn't matter much anyway.
If you do want it permanently stored, the filesystem is the best way. You'll need to synchronize access to it of course.
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 a multiple Activity application that progresses the user from entering an IP/Host address, to entering some data (another Activity), to viewing a stream of video frames (yet another Activity). I share the Socket between the Activities by creating a singleton. Is this considered a bad pattern to use for an object that cannot be serialized?
I have looked all morning through some of these posts and others through out the web and the best that I can come up with is there is no real easy way, but this one seems very easy to me. The only other approach I think has merit is a custom Application object.
Any insight by people who have worked with singletons across Activities I would really like to hear of any problems I may not be aware of that might get me later... Thanks!!
The downside to your approach is that you cannot rely on the singleton's data structures to always be kept around in memory. Your best bet is to persist information in either SharedPreferences or a SQLite database.
It sounds like your singleton might be a good candidate for a Service. Services are meant for long runnning operations that do not have any UI. Multiple Activities can bind to a service and interact with it. Unlike a singleton, if/when your service gets killed, you will get lifecycle hooks to deal with it appropriately. You can also set it to be restarted when appropriate.
This is a question I've now had for a few different apps I've built, and I have yet to be satisified with any of the solutions I've come up with. I thought I'd put it out there to the community to see other solutions there might be.
Let's say you have an Activity that downloads a complex tree of data (in this case via json, but it could be anything), unmarshalls that data to a set of java objects (in this case using gson, but again, could be whatever), then spawns additional activities to view different parts of that data. There might be one activity to view Trips in your response, and another to view Flights in those trips, and maybe another to view Passengers of those flights.
My initial implementation of this app was to unmarshall all the Trips in the first activity, then pass them by value (as an extra in the intent) to the TripActivity. The TripActivity then passes individual flights to the FlightActivity, and so on.
The problem with this is that there's a noticeable pause between activities while the app serializes and deserializes the data. We're talking several seconds. The pause is quite noticeable when my tree uses Serialization or Parcelable to pass data around. Initial performance testing with using google's Parcelable instead show a roughly 30% speedup over serialization, but Parcelable is difficult to work with and doesn't seem to handle circular object references well like Serialization does, and besides it still pauses for almost as many seconds, so I've put that experiment on the backburner while I try other things.
So then I tried moving the tree of objects directly into the Application class. Each activity just gets the tree directly from the app whenever it needs it. This makes performance quite snappy, but handling corner cases like unexpected activity start/stops (either due to activity crashes or because the activity has been closed temporarily to make more memory available, or whatever other cause) seems tricky. Perhaps it's no more than implementing onSaveInstanceState(), I'm not sure, but the solution seems a bit hacky so I haven't investigated further yet.
So in search of a less cobbled-together solution, I tried creating a custom ContentProvider to store and retrieve my objects. Since ContentProviders can be configured to run in-process using multiprocess=true, I thought that would be an excellent way to avoid serialization costs while doing something more "standard" than storing data in the Application object. However, ContentProviders were clearly not intended to return arbitrary object types -- they only support types such as numbers, strings, booleans, etc. It appears I can finagle one to store arbitrary objects by using ContentResolver.getContentProviderClient().getLocalContentProvider() and accessing my custom class directly, but I'm not sure that's less hacky than storing data in the Application object.
Surely someone must have a good solution to this problem. What am I doing wrong?
In addition to fiXedd's solution, another one is to use a local service. Have the service "own" the objects, with activities calling service APIs to get whatever it needs. The service can also be responsible for fetching and parsing the data, encapsulating that bit of logic.
The Application object is the "red-headed step-child" of Android components. Members of the core Android team have come out against the practice of creating custom Application subclasses, though it is certainly supported by the API. Having engineered one ADC2 200 application that leveraged a custom Application subclass, I can say that I should have gone with a service in my case as well. Live and learn...
By using the local binding pattern, your service will automatically be created and destroyed as needed, so you don't have to worry about that. And, by definition, a local service runs in the same process/VM as your activities, so you don't have to worry about marshaling overhead like you would in the ContentProvider scenario.
The way I'm handling this in one of my apps is downloading the data then shoving it into a database. This way I don't have to carry all those objects around (which, IIRC, eat about 1kb each just for the object instantiation) and I can easily pull just the data that I need. I don't know if this will work for you, but it worked for my use-case.
Another approach would be to save the data objects to a shared preferences file. That's how we implemented one of our apps, but I didn't like that approach because it seems too slow.
It's bad coding practice, but the fastest way may be to just use a service to parse the data and save the data to a static class that you can use for the rest of the app's life.