Passing objects between activities in android
Passing data with intent
Passing simple data types (String, int, double,…ect) between activities is easy. We can just put the them to intent with unique key and send it to an another activity.
But it is bit complex when passing custom objects between activities. This is the place where
serialization
comes.
What is Serialization?
Serialization is converting data from a fast, efficient, internal representation to something that can be kept in a persistent store or transmitted over a network.
Converting data to its serialized form is often called
marshaling
it. Converting it back to its live, in-memory representation is called deserializing orunmarshaling
.
More about serialization - https://www.inkling.com/read/programming-android-mednieks-1st/chapter-6/serialization
- In android there are two ways to achieve
marshaling
andunmarshaling
of java objects
- Serializable (Implment object as Serializable)
- Parcelable (Implement object as Parcelable)
Serializable vs Parcelable
Serializable is a marker interface, which implies the user cannot marshal the data according to their requirements. So when object implements
Serializable
Java will automatically serialize it.Parcelable is android own serialization protocol. In Parcelable, developers write custom code for marshaling and unmarshaling. So it creates less garbage objects in comparison to Serialization
The performance of Parcelable is very high when comparing to Serializable because of its custom implementation
It is highly recommended to use Parcelable implantation when serializing objects in android
Parcelable objects
When need to pass custom object between activities we can mark the object as Parcelable(Implement the Parcelable interface). Then object capable to put in to an intent with
intent.putExtra
methodFollowing is an example implementation of parcelable object(
User
)
https://github.com/erangaeb/dev-notes/blob/master/android-parcelable/User.java
This is a simple object which keeps user related data.
User
object implements as Parcelable.There are two methods to override from
Parcelable
interfacedescribeContents
andwriteToParcel
. Actual object serialization do inwriteToParcel
method.
/**
* Define the kind of object that you gonna parcel,
* You can use hashCode() here
*/
@Override
public int describeContents() {
return 0;
}
/**
* Actual object serialization happens here, Write object content
* to parcel, reading should be done according to this write order
* param dest - parcel
* param flags - Additional flags about how the object should be written
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(username);
dest.writeString(email);
dest.writeString(password);
}
- Object need to have
Parcelable.Creator
. This field is needed for Android to be able to create new objects, individually or as arrays
/**
* This field is needed for Android to be able to
* create new objects, individually or as arrays
*
* If you don’t do that, Android framework will raises an exception
* Parcelable protocol requires a Parcelable.Creator object
* called CREATOR
*/
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
public User createFromParcel(Parcel in) {
return new User(in);
}
public User[] newArray(int size) {
return new User[size];
}
};
This User object is a simple parcelabel object, There can be some more complex objects, for an instance you have an object that references another object. In this kind of scenario they would both need to be Parcelable
Following is an example of more complex parcelable object(
Sensor
)
https://github.com/erangaeb/dev-notes/blob/master/android-parcelable/Sensor.java
-
Sensor
object contains few special fields
1. User object(user)
2. User list(sharedUsers)
3. boolean field(isMySensor)
- When writing
user
object of sensor to the parcel, it uses
dest.writeParcelable(user, flags);
- When reading
user
object from parcel it needs class loader
this.user = in.readParcelable(User.class.getClassLoader());
- When writing user list(
sharedUsers
) to the parcel, it uses
dest.writeTypedList(sharedUsers);
- When reading user list(
sharedUsers
) from parcel it needsUser.CREATOR
instance
this.sharedUsers = new ArrayList<User>();
in.readTypedList(sharedUsers, User.CREATOR);
- Instead of writing boolean value to parcel, we convert it to an integer value and save it as an integer(since no method to write booleans directly to the parcel)
dest.writeInt(isMySensor ? 1 : 0);
- When reading the boolean value, we get the boolean value from the saved integer
this.isMySensor = (in.readInt() != 0);
Pass the object with intent
- In starting activity we can set the parcelable object to an intent
User user = new User("1", "u", "u", "u");
ArrayList<User> userList = new ArrayList<User>();
Sensor sensor = new Sensor("1", "s", "s", true, user, userList);
intent.putExtra("com.score.senzors.pojos.Sensor", sensor);
- In destination activity we can get the parcelable object from intent extras(bundle)
Bundle bundle = getIntent().getExtras();
Sensor sensor = bundle.getParcelable("com.score.senzors.pojos.Sensor")
Written by eranga bandara
Related protips
5 Responses
Parcelable looks like the best way to do it. Serializable the easiest. But there is no escaping having to add the objects as extras to the intent using keys and getting it back from the other end etc.
I had always wondered why this can't be as simple as calling into a method of the other activity. I recently wrote a utility library that makes it almost as simple as that. You can check it out here(https://github.com/noxiouswinter/gnlib_android/wiki#gnlauncher).
I have not profiled this yet but it may or may not be the most efficient approach. Feel free to contribute to the project if you can think of ways to improve it.
When I have to transfer some custom object which on its content there're other objects that are from a third-party integration (so, I cant make them implement Serializable or Parcelable for example), this approach cannot happen. There's another way out?
There is a cool library, Parceler, that can help you with third party objects not implementing Parcelable, but also with your classes. However it has its downfalls - for more info see http://nemanjakovacevic.net/blog/english/2015/03/24/yet-another-post-on-serializable-vs-parcelable/
Parcelable or Serializable, In both ways we have to add extra code and still get performance and memory hit. especially when we start passing more complex objects this is can become a serious performance hit.
If we look in the Android Docs then there is another way of passing objects which is much faster. I have created a simple yet powerful class for this purpose (https://github.com/asifmujteba/AndroidObjectStore), Please have a look at it and let me know! Thanks.
Is a good practice setting the extra as JSON String?