Passing/Using non primitive objects between Activities - android

I need to pass a List of my objects between activities. I do not want to use parcelable or serialize the data each time. I also do not want to save it in a local file or database. That probably leaves me with using static objects.
Lets say I to use ListA between activities Activity1 to Activity2. I ca
Approach1: Create a static ListA in one of those activities and do all my stuff of that static ListA.
Approach2: Create a static list in another class which I use just for storing this List and doing all my stuff on this list. But this means that this stays as long as my process is running and I have to manually set it to null when I do not need it.
Approach3. I am extending the above class to implement it using a static HashMap.
I have two methods one to store the list in a static HashMap using a unique key and another method to retrieve the list and remove it each time data is retrieved so that the List is no longer present in the static HashMap. So we essentially have to pass only the random key generated to store data between activities which I can pass as an extra using Intents.
Will there be any issues when I use any of the above approaches and which will be the best approach.

I'd consider creating an Application object and using it like a singleton to access your data. I've described the approach here: http://chrisrisner.com/31-Days-of-Android--Day-7%E2%80%93Sharing-Data-Between-Activities. Some people don't seem to like using the Application object in this manner but it makes more sense to me than putting a static object on an Activity.

Uggg statics! Man I wish all developers understood global variables are bad and how they make your program more brittle and your life hell. We only been talking about how bad they are for 30+ years, but unfortunately no one figures this out until they've utterly hung themselves on them.
First I'll say serializing your data is fast. There are great tools out there that will serialize your objects quickly that you can use I prefer http://flexjson.sourceforge.net for this.
So if you are just outright opposed to this you can pass this object through the Application by subclassing it, declaring your implementation in your Android Manifest, and each activity has access to the Application instance:
public class MyActivity extends Activity {
public void onCreate( Bundle bundle ) {
MyApplication application = (MyApplication)getApplication();
Object anInstanceFromAnotherActivity = application.getSomeInput();
}
}
The downside to this is when your application is reclaimed if the user returns to your application the memory is gone, and you can't get that input you might need of your screen. Android framework is trying to make you serializing things in the bundles because if it decides to destroy your application you can always rebuild yourself from the bundle. Now there are short cuts you can take like redirecting people to start over if the Application has been reclaimed, but those depend upon your program and what its doing if they make sense.
That's where using serialization wins out over all other forms of persistence (parcelables, files, databases) because it can be done in one line of code.

Related

Android, performance of transferring data between activities

Which one of two ways below has better performance for transferring data between activities?
Activity1: putExtra("id" , customerId)
Activity2: Select on the table and fill Customer object
Activity1: putExtra("customer", customer)
Activity2: Customer customer = (Customer)getIntent().getExtras().getSerialaizable("customer");
I mean send a unique item (like id) to the next activity and then select it from data base OR send the whole object to the next activity and cast it?
Obviously first way. You just send the ID of the object and then read it from the database in second Activity. The other way involves serialization/deserialization which costs CPU-cycles. Even using Parcelable will still use significant CPU-cycles.
On the other hand, I doubt that you would notice any performance penalties unless you are doing this for a bazillion objects. Do whatever is more straightforward and easier to understand/maintain.
Serializable is not recommended in android, check parcelable it's faster.
Serialization vs DB depends on object complicity, only profiling can show the picture, but for a one object it's neglectable.
The fastest way would be to store object in memory and share through singleton.

How to exchange an object between different Android Activities?

My application has a list of clients (with only name and age displayed) and I want to be able to edit/add more info about them that is not visible in the list.
So whenever I click on a client, I want to start a second activity with all the info about him.
Can I use an intent for this? Can I pass a full Object (Client) at once with an intent?
I've looked through these two topics, but I haven't found my answer yet:
How to exchange data (objects) between different Android Activities?
How do I pass data between Activities in Android application?
Thanks in advance.
Look at this answer: How to pass an object from one activity to another on Android
//to pass :
intent.putExtra("MyClass", obj);
// to retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");
I would suggest you look into saving these in the SharedPreferences file. Build a singleton AppUtil class and add functionality to save data in the shared preferences there as well as being able to retrieve said data
If you have a large amount of information being stored for the clients then you should look into SQLite as database storage.
The more pratice way is create a class to hold every objects that you need to change between the activities. Like that:
public class MyHolderObjects {
public static MyObjectType mObject;
}
before start the new activity (or whatever you goes to use it), instantiate (create) the object in MyHolderObjects. And use it everywhere you need :). I prefer this approach instead serialize the object.

Transferring large amounts of data to Activity using putExtra();

The application passes large number of objects (about 150 objects after parsing JSON format) via intent.putExtra();
Among them are serialized objects.
And the process of opening a new activity takes about 2 seconds...
Is there a way to speed up this process?
If you just want to pass data from one activity to another you can just use a static variable that is accessible from both activities. This eliminates the need to serialize and deserialize all the objects. Example:
public class Globals {
public static List<MyObject> myObjects;
}
In one activity you can set the data you want to pass in Globals.myObjects and the receiving activity can get it from there.
Be aware that this mechanism does have some drawbacks (like when Android kills your process and restarts it later). However, this can be the least troublesome way to simply hand a lot of objects from one activity to another.
One suggestion could be:
Use parceable where you are using serializable
Another suggestion could be:
Use something else to save/restore the data. e.g. a database
I think using a Singleton class for sharing large amount of temporary data between activities is a great way to go. Keeps it really quick and simple.
Although it can be done through Android Parcelable but it has storage limitation which can cause this error "!!! FAILED BINDER TRANSACTION !!!"

Android : Static variable null on low memory

I have an application which has some static variables.
These variables are stored in an independent Class named DataContext.
These variables are initialized from raw files at the application start (a method named DataContext.initConstant() is called in the onCreate() of MyApplication which extends Application).
(EDIT : the initConstant method use an AsyncTask to load this data from files).
When my application comes to the background for a certain time or when my application used to much memory, these static variables become null.
How can it be prevented?
If not what should I do with my static variables?
I have other data which are stored in static variables to be used across different activities, but I clear them or pass them to null in the onLowMemory() of MyApplication.
What is the best way to keep some data accessible between activities if these data are too big to be serialized in an Intent, a database can't be used (for whatever reason), and can't be stored in files through serialization either?
You can't. Android needs to free up memory from time to time. Imagine if all applications had a ton of static data that is supposed to be resident forever - how would you fit that in memory? It's a mobile phone. It doesn't have virtual memory.
(and 3): Anything that is intended to be persistent needs to be stored, either via SharedPreferences, a Sqlite database, or a file.
Most likely the issue is that your application is being killed while it is in the background, and then recreated when you come back to it. Check out the Activity Lifecycle documentation on when this might occur for a single activity. You need to make sure that you move anything stored in memory to more permanent storage at the correct point in time to avoid losing that information if the app gets killed.
I'm not sure what exactly you are storing, but it sounds like using Shared Preferences might work well. This page on Data Storage explains a number of different ways of more permanently storing data, including Shared Preferences.
If you weren't using raw files, I'd advise initializing when the class is loaded.
For instance,
public static Map<?,?> myStaticMap = new HashMap<?,?>();
static { //fill myStaticMap }
You do have some bigger concerns to worry about if you are loading files that way. For instance, what about I/O errors, or latency issues? You will get warnings in gingerbread (if you enable them) for doing I/O in your main thread. Perhaps you should have an object to retrieve these values instead of a class with static fields. (perhaps with a static cache, although you should synchronize on it before checking/changing it)
I assume this is a data cache problem.
Storing data in static class is not guaranteed to work when user swap apps often. Android system will reclaim any background activity when memory is low. Static class is definitely among this category.
The proper way to do it is to use sharedPreference to persist cache data.
You can create your own getter and setter of the data you want and wrap it around sharedPreference object. When you access using getter, you should always check if the value is empty or expired. You can store an update_time when using setter.
For activity specific data, you can just use getPreference(permission), if you want to share data across activities and other applications components, you can use getSharedPreference(name, permission).
Normally, the permission will be MODE_PRIVATE such that the data can only be accessed within your application.
You should group data and store in difference sharedPreference object. This is good practice because when you want to invalidate that group of data, it is just a matter of one liner.
editor.clear(); editor.commit()
If you want to cache complex object, you should serialize it. I prefer JSON format. So you need some conversion mechanism in place. To do this, I will create my data object class extending JSONable class. JSONable class will have toJSON() method and readFromJSON(). This is convenient when restore and serialize data.
I store a User object and a Client object in my static scope. I have noticed from time to time the reference becomes null. So now in my getters I check to see if this value is null and if so I restart the app.
Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
I could have also chosen to reload the Client because I store the Access Token in prefs however I do so much initialization that I decided restarting the app would the best idea.
In your onResume() method you could query the static data to see if it is present and if not, load it back in again.
Instead of using the static variable u can use the shared preference for storing the value.
Note: for shared preference also you should not give heavy load.
I have solved this problem by having the super class with getter and setter function for storing and retrieving shared preference variable.
All class in my application extended the super class instead of activity.

Passing data of a non-primitive type between activities in android

Suppose you want to start a new activity and pass it some data from the current activity. If the data is of a primitive type you could simply use an intent and add extras, but how would you do this for more complex data structures like arraylists or objects?
You have a few options:
You could wrap the more complex structure in a class that implements the Parcelable interface, which can be stored in an extra
You could wrap the more complex structure in a class that implements the Serializable interface, which can be stored in an extra
You use static data members to pass stuff around, since they are all in the same process
You use external storage (file, database, SharedPreferences)
As the person who just posted noted, use a common component, such as a custom Application or a local Service
What you do not want to do is pass big stuff via extras. For example, if you are creating an application that grabs pictures off the camera, you do not want to pass those in extras -- use a static data member (icky as that sounds). Intents are designed to work cross-process, which means there is some amount of data copying that goes on, which you want to avoid when it is not necessary for big stuff.
One option I am aware of is storing the data you are using in an Application object which all your activities can retrieve from context.
I have also heard of using Google Protocol Buffer to achieve a higher performing solution

Categories

Resources