Photo by Jørgen Håland on Unsplash
Deep Clones
There are many ways to create deep clones of an object, from Java’s Clone()
function to Copy Constructors to custom implementations. All methods come with their own problems and a lot of boilerplate code.
With Parcelable and advent of Kotlin, creating simple deep clones can be of no effort in your android project.
Why Parcelable?
Serialization is a technique to convert objects into a byte stream and Deserialization vice versa. In this process totally new objects are created (i.e. Object’s clone).
Serialization will create deep clones of the entire object graph, unlike shallow clones, where only the parent object is cloned and references of children objects are copied to the new object. Kotlin’s copy()
function creates shallow clones.
There are 2 ways to serialize objects in android
- Parcelable
- Serializable
Parcelable is android’s replacement to Java’s Serializable. Unlike Serializable, Parcelable does not rely on reflection which makes it much faster and memory efficient.
Though smartphones today have come a long way, performance tuning and memory management are never not a problem. Choosing Parcelable over Serializable can be of help.
How does it work?
Let’s say we have a Person
object that we need to clone.
@Parcelize
data class Person(val name:String,val email:String):Parcelable
Following method is the secret sauce of this article. It leverages Parcelable to do the cloning. I’ve made it generic to work with all type of objects.
fun <T : Parcelable> deepClone(objectToClone: T): T? {
var parcel: Parcel? = null
return try {
parcel = Parcel.obtain()
parcel.writeParcelable(objectToClone, 0)
parcel.setDataPosition(0)
parcel.readParcelable(objectToClone::class.java.classLoader)
} finally {
//it is important to recyle parcel and free up resources once done.
parcel?.recycle()
}
}
Now to create clone and print results.
..
val bob = Person(name="Bob",email="bob@builder.com")
val bobClone = deepClone(bob)
Log.d("Clone Parcelable ->", "bob's content $bob")
Log.d("Clone Parcelable ->", "clone content $bobClone")
Log.d("Clone Parcelable ->", "are references equal ${bob === bobClone} ")
Log.d("Clone Parcelable ->", "is content equal ${bob == bobClone} ")
..
A similar result can be achieved using the Serializable interface.
Pros
- Less boilerplate code
- Easy to implement
- Faster than serializable
Cons
- Parcelable interface must be implemented throughout the graph of the object to be cloned.
Conclusion
When creating clones its rarely one size fits all. It is subjective to the programmer and the requirements of the project.
Knowing this technique adds one more tool to your arsenal.
4 comments On Deep clones with Android Parcelable
Resourceful article. Looking forward to more!
Glad to hear that 🙂
Nice Article
Looking for more
Thanks Ravi. 🙂