Passing data across Activities / Fragments

Tompee Balauag
Familiar Android
Published in
3 min readMay 1, 2018
“A subway train passing in front of a woman with a black leather bag” by Eutah Mizushima on Unsplash

Last week, I was tasked with the problem of marshalling data from managed to unmanaged code, and it reminded me of this problem that I had years ago regarding the best way to pass data across activities and fragments.

This topic is not anywhere near novel, but I think it is always relevant. As we all know, it is not easy to pass objects between activities and fragments due to the framework managing the lifecycle and backstack. In this article, we will discuss some ways you can ‘marshal’ these objects.

Serializable

Serializable is a standard Java interface. It is the simplest form of marshalling data. You just implement the Serializable interface and you’re good to go. Let’s take a look at an example.

We create two activities and a warrior model that is serializable. We instantiate the warrior object in the first activity, and pass it to the second activity along with the intent. Running this program will output this line in the logcat.

D/SecondActivity: My warrior is Hercules with weapon sword

Now, how does serializable works? Serialization converts the object data to a stream of byte data. It does this by translating the object information and all its parent information and fields into a byte stream. On the other end, the bytestream is read and the expected object is created and its field is set using reflection.

This approach can suffer in terms of performance due to the fact that reflection is used and a lot of intermediate objects are created that can force garbage collection. This is however already sufficient for small POJOs as performance cost is not noticeable.

Parcelable

Parcelable is an Android Interface. It is more tedious to use as it requires you to implement a handful of methods. Let’s take a look at an example again.

We define a parcelable model and use the same two activities from before. Running this code will output this log.

D/SecondActivity: My warrior is Zeus with weapon Spear

Now let’s take a closer look. Parcelable requires you to pack your data in an orderly fashion. If you take a look at the writeToParcel method, we are adding the name and weapon in the parcel. The order of writing matters since parsing is sequential as well. It also requires us to implement a constructor that accepts a parcel. A static parcelable creator must also be implemented. This allows you to customize the object creation, or use a factory if necessary.

The advantage of parcelable is the absence of reflection. This provides a big performance boost and this is not an overstatement.

Coupling

One of the most convenient way to pass data is to create a static object that can be used as handover. I termed it as coupling as it introduces hard coupling between two objects.

In the above code, we defined a static object that contains a warrior. The first activity set the warrior while the second activity uses it. This is easy and fast but it is hardly maintainable and scalable. It also creates unnecessary dependencies.

Event Aggregator

I first used this approach when I was working on a C# project. The idea is pretty intuitive. You have some sort of event publisher and anyone can subscribe and unsubscribe to it at will. This is very convenient and easy to use. Now let us create our own event aggregator. First, we need to define an event interface.

All the objects that will be published should implement this interface. Now, let us create the event aggregator itself.

The aggregator contains a map of event types and list of actions. When we subscribe to an event type, we pass the action that should be invoked. Publishing only requires the message itself. Unsubscribe removes the action from the map. Now let us update the two activities above.

Running this will produce the output below.

D/MainActivity: My warrior is John Wick with weapon gun

Event aggregators advantages include ease of use, preservation of object instance, and is generic. However, this approach falls under the Ambient Context Anti-Pattern and is generally discouraged in Dependency Injection.

That’s it for marshalling data. Time to weigh the cost and benefits.

--

--