使用 Serialized 作为 Android 导航组件的深层链接参数

Pio*_*ski 5 android android-navigation android-architecture-navigation android-deep-link android-jetpack-navigation

Serializable使用深层链接时是否可以使用自定义对象作为片段参数?

我已经尝试了以下操作 - 在我的导航图 XML 文件中,我添加了以下几行:

<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>
Run Code Online (Sandbox Code Playgroud)

EventId可序列化数据类在哪里:

data class EventId(val value: Long) : Serializable
Run Code Online (Sandbox Code Playgroud)

然后,当我尝试使用 URL 运行应用程序时myapp://event/4002,会引发以下异常:

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)
Run Code Online (Sandbox Code Playgroud)

long用( )替换 typeapp:argType="long"解决了问题 - 没有例外,一切都按预期进行。

导航库似乎不知道如何将 URL 中的原始值转换为我的EventId类。是否可以以某种方式注册一个知道如何转换它的适配器?或者也许还有另一种解决方案?

Hen*_*ärd 0

据我所知,除了您所做的之外,您只有另一种选择:Parcelable

我认为在这种情况下就足够了,但我不确定,但即使没有,这对于未来的 Android 开发来说也是一个很好的建议,例如当您需要在 Activity 或片段之间发送数据时。

特别是我看到您正在使用 Kotlin,它有一个正确实现它的辅助方法,请参阅:Parcelize

有了它,您的数据类将如下所示:

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

Run Code Online (Sandbox Code Playgroud)

旁注:出于各种原因,不鼓励使用 Serialized 接口。来自长期从事 Java 工作的Joshua Bloch所著的《Effective Java》一书:

Item 85: Prefer alternatives to Java serialization
Run Code Online (Sandbox Code Playgroud)

如果您仍然需要使用 Serialized,本书将介绍必要的细节。