I have one activity which is the main activity used throughout the app and it has a number of variables. I have two other activities which I would like to be able to use the data from the first activity. Now I know I can do something like this:
GlobalState gs = (GlobalState) getApplication();
String s = gs.getTestMe();
However I want to share a lot of variables and some might be rather large so I don't want to be creating copies of them like above.
Is there a way to directly get and change the variables without using get and set methods? I remember reading an article on the Google dev site saying this is not recommended for performance on Android.
If your intention is to call other Activities from the current Activity, you should use Intents. Your focus could be less on persisting data than on sharing it on an as-needed basis.
However, if you really need to persist these values then you could persist them in some kind of structured text file or database on local storage. A properties file, XML file, or JSON file could store your data and be easily parsed during activity creation. Don't forget also that you have SQLite on all Android devices, so you could store them in a database table. You could also use a Map to store key-value pairs and serialize the map to local storage, but this might be too cumbersome to be useful for simple data structures.
There is a new and better way to share data between activities, and it is LiveData. Notice in particular this quote from the Android developer's page:
The implication of this is huge - any model data can be shared in a common singleton class inside a
LiveData
wrapper. It can be injected from the activities into their respectiveViewModel
for the sake of testability. And you no longer need to worry about weak references to prevent memory leaks.Well I have a few ideas, but I don't know if they are what your looking for.
You could use a service that holds all of the data and then just bind your activities to the service for data retrival.
Or package your data into a serializable or parcelable and attach them to a bundle and pass the bundle between activities.
This one may not be at all what your looking for, but you could also try using a SharedPreferences or a preference in general.
Either way let me know what you decide.
Using the hashmap of weak reference approach, described above, and in http://developer.android.com/guide/faq/framework.html seems problematic to me. How are entire entries reclaimed, not just the map value? What scope do you allocate it in? As the framework is in control of the Activity lifecycle, having one of the participating Activities own it risks runtime errors when the owner is destroyed in advance of its clients. If the Application owns it, some Activity must explicitly remove the entry to avoid the hashmap from holding on to entries with a valid key and a potentially garbaged collected weak reference. Furthermore, what should a client do when the value returned for a key is null?
It seems to me that a WeakHashMap owned by the Application or within a singleton is a better choice. An value in the map is accessed via a key object, and when no strong references to the key exist (i.e. all Activities are done with the key and what it maps to), GC can reclaim the map entry.
All of the aforementioned answers are great... I'm just adding one no one had mentioned yet about persisting data through activities and that is to use the built in android SQLite database to persist relevant data... In fact you can place your databaseHelper in the application state and call it as needed throughout the activates.. Or just make a helper class and make the DB calls when needed... Just adding another layer for you to consider... But all of the other answers would suffice as well.. Really just preference
Here a compilation of most common ways to achieve this:
WeakReferences
TL;DR: there are two ways of sharing data: passing data in the intent's extras or saving it somewhere else. If data is primitives, Strings or user-defined objects: send it as part of the intent extras (user-defined objects must implement
Parcelable
). If passing complex objects save an instance in a singleton somewhere else and access them from the launched activity.Some examples of how and why to implement each approach:
Send data inside intents
On the second activity:
Use this method if you are passing primitive data or Strings. You can also pass objects that implements
Serializable
.Although tempting, you should think twice before using
Serializable
: it's error prone and horribly slow. So in general: stay away fromSerializable
if possible. If you want to pass complex user-defined objects, take a look at theParcelable
interface. It's harder to implement, but it has considerable speed gains compared toSerializable
.Share data without persisting to disk
It is possible to share data between activities by saving it in memory given that, in most cases, both activities run in the same process.
Note: sometimes, when the user leaves your activity (without quitting it), Android may decide to kill your application. In such scenario, I have experienced cases in which android attempts to launch the last activity using the intent provided before the app was killed. In this cases, data stored in a singleton (either yours or
Application
) will be gone and bad things could happen. To avoid such cases, you either persist objects to disk or check data before using it to make sure its valid.Use a singleton class
Have a class to hold the data:
From the launched activity:
Use application singleton
The application singleton is an instance of
android.app.Application
which is created when the app is launched. You can provide a custom one by extendingApplication
:Before launching the activity:
Then, from the launched activity:
Static fields
The idea is basically the same as the singleton, but in this case you provide static access to the data:
From the launched activity:
HashMap of
WeakReferences
Same idea, but allowing the garbage collector to removed unreferenced objects (e.g. when the user quits the activity):
Before launching the activity:
From the launched activity:
You may or may not have to pass the object id using the intent’s extras. It all depends on your specific problem.
Persist objects to disk
The idea is to save the data in disk before launching the other activity.
Advantages: you can launch the activity from other places and, if the data is already persisted, it should work just fine.
Disadvantages: it’s cumbersome and takes more time to implement. Requires more code and thus more chance of introducing bugs. It will also be much slower.
Some of the ways to persist objects include: