Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Serializable as deep link argument with Android Navigation Component

Is it possible to use a custom Serializable object as a fragment argument when using deep links?

I've tried the following - in my navigation graph XML file I've added following lines:

<fragment
    android:id="@+id/eventFragment"
    android:name="com.myapp.EventFragment"
    android:label="EventFragment">

    <argument
        android:name="event"
        app:argType="com.myapp.EventId" />

    <deepLink app:uri="myapp://event/{event}" />

</fragment>

Where EventId is a serializable data class:

data class EventId(val value: Long) : Serializable

Then, when I'm trying to run my application with an URL myapp://event/4002, the following exception is thrown:

Caused by: java.lang.UnsupportedOperationException: Serializables don't support default values.
        at androidx.navigation.NavType$SerializableType.parseValue(NavType.java:834)
        at androidx.navigation.NavType$SerializableType.parseValue(NavType.java:787)
        at androidx.navigation.NavType.parseAndPut(NavType.java:96)
        at androidx.navigation.NavDeepLink.getMatchingArguments(NavDeepLink.java:99)
        at androidx.navigation.NavDestination.matchDeepLink(NavDestination.java:366)
        at androidx.navigation.NavGraph.matchDeepLink(NavGraph.java:79)
        at androidx.navigation.NavController.handleDeepLink(NavController.java:540)
        at androidx.navigation.NavController.onGraphCreated(NavController.java:499)
        at androidx.navigation.NavController.setGraph(NavController.java:460)
        at androidx.navigation.NavController.setGraph(NavController.java:425)
        at androidx.navigation.NavController.setGraph(NavController.java:407)
        at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:236)

Replacing type with long (app:argType="long") solves the issue - there is no exception and everything works as expected.

It seems like the navigation library does not know how to convert the raw value from the URL to my EventId class. Is it possible to somehow register an adapter which knows how to convert it? Or maybe there is another solution?

like image 492
Piotr Aleksander Chmielowski Avatar asked Nov 07 '22 12:11

Piotr Aleksander Chmielowski


1 Answers

As far as I am aware, you only have one other alternative to what you have done: Parcelable.

I think it will be sufficient in this case, but I am not sure, but even if it doesn't, this will be a good recommendation for any future Android development when you for example need to send data between Activities or fragments.

Especially as I can see you are using Kotlin, which has a helper method for implementing it correctly, see: Parcelize.

With it, your data class would simply look like this:

@Parcelize
data class EventId(val value: Long) : Parcelable

Side note: Usage of the Serializable interface is discouraged for various reasons. From the book Effective Java written by Joshua Bloch who worked on Java for a long time:

Item 85: Prefer alternatives to Java serialization

If you still have to use Serializable, the book will cover the necessary details.

like image 52
Henrik Gyllensvärd Avatar answered Nov 14 '22 22:11

Henrik Gyllensvärd