4

I have following setup:

Kotlin data class:

data class Error(val throwable: Throwable, val reloadAction: (() -> Unit)? = null) : Serializable

Initialization of class:

val instance = Error(throwable,this::loadData)

Where this is ViewModel from Android Architecture components

When I'm passing this data class to parcelable:

parcel.writeSerializable(instance as Serializable)

I get following exception:

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.mypackagename.Error)
        at android.os.Parcel.writeSerializable(Parcel.java:1468)
        at com.mypackagename.CustomView$Companion$SavedState.writeToParcel(CustomView.kt:177)
...
Caused by: java.io.NotSerializableException: com.mypackagename.ExampleViewModel

In this question: Is there a way to pass a function reference between activities? is following answer:

It will actually be Serializable if it is a function reference (SomeClass::someFunction) or a lambda. But it might not be, if it is some custom implementation of the functional interface () -> Unit, so you should check that and handle the cases when it's not.

Is this my case? Or data class cannot be serialized when function is function of non serializable object (ViewModel)? Are there any other possibilities how to pass function literal as Serializable inside data class?

Jarda Havelik
  • 502
  • 1
  • 7
  • 18
  • I've created a wrapper TrackedReference that is parcelable and serializable without requiring marshaling for the underlying type: https://stackoverflow.com/a/64944753/3405387 – Lukas Nov 21 '20 at 16:25

2 Answers2

4

The problem ist the view model: com.mypackagename.ExampleViewModel. This class is not serializable.

If you use a function reference, the target object - in this case the view model- must be serializable too.

Rene
  • 5,730
  • 17
  • 20
  • Okay, that's what I thought. Is there any other option? Obviously I cannot do my viewmodel serializable. – Jarda Havelik Oct 17 '18 at 06:48
  • You could change your function type to `(ReloadContext) -> Unit`. Every reload function now gets an context object. This context provides access to all transient / non-serializable objects required for reloading the data. Whenever you invoke the reload function, you have to provide a context object. The reload function itself should reside in a serializable class, so that a function reference is serializable as well. – Rene Oct 17 '18 at 10:21
4

I had similar issue, my problem was that I didn't expect a data class not to be Serializable by default. It is important not to forget to implement the Serializable interface.

Vojtěch
  • 11,312
  • 31
  • 103
  • 173