Kotlin android parcelable
Asked Answered
R

4

9

I've used auto generated feature of android plugin for android studio and it generated me the following code, but I can't understand why is there need for final val for CREATOR field ? I see final keyword for the first time in kotlin.

data class Person(
        val name: String,
        val surname: String
) : Parcelable {
    constructor(source: Parcel): this(source.readString(), source.readString())

    override fun describeContents(): Int {
        return 0
    }

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest?.writeString(name)
        dest?.writeString(surname)
    }

    companion object {
        @JvmField final val CREATOR: Parcelable.Creator<Person> = object : Parcelable.Creator<Person> {
            override fun createFromParcel(source: Parcel): Person {
                return Person(source)
            }

            override fun newArray(size: Int): Array<Person?> {
                return arrayOfNulls(size)
            }
        }
    }
}
Roxy answered 22/5, 2016 at 9:7 Comment(0)
S
9

In Kotlin classes and members are final by default. In other words the following declarations have the same bytecode:

@JvmField final val CREATOR: Parcelable.Creator<Person> = PersonCreator()
@JvmField val CREATOR: Parcelable.Creator<Person> = PersonCreator()

So while the generated code has final keyword and it is not an error it is redundant.

Even though classes and members are final by default there are still a need for final modifier in Kotlin. One example would be to mark open method as final in derived class:

open class Base {
    open fun test(){}
}

open class DerivedA : Base(){
    final override fun test(){}
}

class DerivedB : DerivedA() {
    override fun test(){} //error: 'test' in 'DerivedA' is final and cannot be overriden
}

While it's a good practice to make public static field final in java there's no strict requirement for the Parccelable.Creator field to be marked as such:

Classes implementing the Parcelable interface must also have a non-null static field called CREATOR of a type that implements the Parcelable.Creator interface.

Sterrett answered 22/5, 2016 at 9:31 Comment(0)
T
7

In Kotlin you can use the @Parcelize Kotlin Android Extension:

@Parcelize
data class User(val id: String, val name: String) : Parcelable

This is a compiler plugin that automatically generates the Parcelable implementation for you.

This page on the Kotlin docs gives more details about it, including requirements, supported types and how to create custom parcelers for unsupported types.


If you are curious and you want dive into the technical details of the implementation, see the Kotlin Evolution and Enhancement Process Compiler Extension to Support android.os.Parcelable.


This feature was experimental until Kotlin 1.3.40. If you are still using a Kotlin version earlier than 1.3.40, you need to enable the experimental features to use this:

android {
    // Enable @Parcelize
    // You only need this for Kotlin < 1.3.40
    androidExtensions {
        experimental = true
    }
    ...
}
Triplet answered 3/5, 2019 at 12:21 Comment(0)
I
2

Use @Parcelize annotation to data class and extends Parcelable. Kotlin automatically do the rest for you. Example- Person data class.

@Parcelize
data class Person(val name: String, val age: Int, val email: String) : Parcelable

You can send value lets press on a button click like below from an activity.

   private val PERSON = "person"

   // first ensure a person object with data
   val person = Person("Shihab Uddin", 30, "[email protected]")

   binding.buttonSend.setOnClickListener {

        val intent = Intent(this, ReceiveParcelableAcitivty::class.java)
        //then put an parcelable extra to intent 
        intent.putExtra(PERSON, person)
        startActivity(intent)

    }

Receivers activity will get the data like

    private val PERSON = "person"
    intent?.let {
        var person = intent.extras.getParcelable(PERSON) as Person
        bind.textViewData.text = " Data Receive: $person"
    }

androidExtensions attribute is no more necessary < kotlin 1.3.40

android {

    // You only need this for Kotlin < 1.3.40
    androidExtensions {
        experimental = true
    }
    ...
}
Impossible answered 11/3, 2020 at 10:42 Comment(0)
R
0

In the latest kotlin and gradle versions (sorry ,i forgot the version number), you need add

plugins {
     id("kotlin-parcelize")
}

in this file build.gradle.kts( Depends on whether your gradle is kotlin or other)

now , you can use it.

import kotlinx.parcelize.Parcelize

@Parcelize
data class User(val id: String, val name: String) : Parcelable
Remembrance answered 24/11, 2023 at 3:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.