I have a class that I use as my data model for a RecyclerView
in order to pass object of this class from one activity to another via Intent
I had to make it Parcelable
The problem is now that I am being able to send the object from one activity to another and retrieve it, so that the app does not crash, but keeps throwing ClassNotFoundException
in the logcat screen.
What am I doing wrong?
----> Person.kt
@Parcelize
class Person(var name: String, var username: String, var address: String, val avatar: Int) : Parcelable
----> in MainActivity.kt
val intent = Intent(this, ProfilePage::class.java)
intent.putExtra("clicked_person",person)
startActivity(intent)
---->. onCreate()
in ProfilePAge.kt
var person = intent.getParcelableExtra<Person>("clicked_person") as Person
And the Exception
E/Parcel: Class not found when unmarshalling: com.example.testkot.kotlinapp.Person
java.lang.ClassNotFoundException: com.example.testkot.kotlinapp.Person
Please remember that the app does not crash, it keeps working but shows the exception in logcat
I've prepared the extension functions below for your convenience to use the Kotlin Parcelables without any warnings.
fun Intent.putParcel(key: String = "parcel_key", parcel: Parcelable) {
val bundle = Bundle()
bundle.putParcelable(key, parcel)
this.putExtra("parcel_bundle", bundle)
}
fun <T : Parcelable> Intent.getParcel(key: String = "parcel_key"): T? {
return this.getBundleExtra("parcel_bundle")?.getParcelable(key)
}
Usage:
//Put parcel
intent.putParcel(parcel = Person()) //any Parcalable
//Get parcel
val person: Person? = intent.getParcel() //auto converts using Generics
After testing a solution in a comment, the following works without throwing any exception
Sending theParcelable
via Bundle
val intent = Intent(this, ProfilePage::class.java)
var bundle = Bundle()
bundle.putParcelable("selected_person",person)
intent.putExtra("myBundle",bundle)
startActivity(intent)
Recovering Parcelable
val bundle = intent.getBundleExtra("myBundle")
var person = bundle.getParcelable<Person>("selected_person") as Person
However, I do not know the difference with my old code in the question and why that old code throws Exception and why this new one does not throw
I guess this is a compatibility issue between Kotlin and Java for the moment. I found an easy solution that allows using only Kotlin and without boilerplate.
val intent = Intent(this, ProfilePage::class.java).apply {
extras?.putParcellable("clicked_person",person)
}
startActivity(intent)
And then to retrieve the value you should use:
var person = intent?.extras?.getParcellable<Person>("clicked_person")
NB: you don't need to cast as Person
For anyone reading this in 2022, starting from Android Tiramisu(API 33) getParcellable<Any>
has been deprecated and we've to use getParcelable(@Nullable String key, @NonNull Class<T> clazz)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With