【问题标题】:How to use safe-args with MPP serializable data如何将安全参数与 MPP 可序列化数据一起使用
【发布时间】:2020-04-09 20:03:17
【问题描述】:

我正在尝试将 safe-args 与 kotlin-multiplatform 类型一起使用,但是在尝试传递可序列化数据时,我在运行时不断遇到同样的问题:

引起:java.lang.IllegalArgumentException: org.kotlin.mpp.mobile.models.MyModel 不可序列化或 可打包。

在我的 nav_host.xml 我有以下内容:

<fragment
    android:id="@+id/aFragment"
    android:name="com.corp.myapp.main.aFragment"
    android:label="aFragment" >
    <action
        android:id="@+id/action_aFragment_to_bFragment"
        app:destination="@id/bFragment"
        app:popUpTo="@id/bFragment"
        app:popUpToInclusive="true">
        <argument
            android:name="myname"
            app:argType="org.kotlin.mpp.mobile.models.MyModel"
            app:nullable="true" />
    </action>
</fragment>

我现在使用的两种方法都得到了完全相同的异常。

第一个是使用 kotlinx-serialization 插件,我有以下类型:

package org.kotlin.mpp.mobile.models

import kotlinx.serialization.Serializable

@Serializable
data class MyModel(val first: String = "", val last: String = "")

第二个我尝试过的第一个不起作用是使用以下扩展的 java.io.Serializable 制作一个特定于平台的 (JVM) 实现:

commondataModels.kt:

package org.kotlin.mpp.mobile.models

expect class MyModel(first: String, last: String)

actualdataModels.kt:

package org.kotlin.mpp.mobile.models

import java.io.Serializable

actual data class MyModel actual constructor(val first: String, val last: String): Serializable

我正在使用生成的方向类在我的 Activity 中进行导航调用:

import org.kotlin.mpp.mobile.models.*


val user = MyModel("Bruce","Lee")
host.findNavController().navigate(AFragmentDirections.actionAFragmentToBFragment(user))

提前感谢您的任何建议!

注意:我可以通过使用 navigate API 传递一个 Bundle 来使一切正常工作,但是我希望它可以与安全参数一起使用。

【问题讨论】:

  • 也许使用@Parcelize
  • @CommonsWare Thx 作为提示,但我有点坚持导入依赖项以使其在我的 MPP 模块中工作

标签: android android-architecture-navigation kotlin-multiplatform android-safe-args


【解决方案1】:

按照 CommonsWare 的建议,使用 @Parcelize(以及扩展名 Parcelable)

诀窍是确保 Parcelable 不会破坏您的通用代码,因为这是 Android 唯一的概念。 为此,在您的常用代码中添加

期望接口 Parcelable

还有:

@UseExperimental(ExperimentalMultiplatform::class) @OptionalExpectation @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.BINARY) 期望注解类 Parcelize()

看起来像这样:

然后在您的 Android 源代码集中,实际使用 typealias:

实际类型别名 Parcelable = android.os.Parcelable

实际类型别名 Parcelize = kotlinx.android.parcel.Parcelize

在其他源集(如iOS)中,把这个放到实际中:

实际界面Parcelable

【讨论】:

  • 嗨!感谢您使用 Parcelable 的想法,我试了一下,但我无法获得依赖项 android.os.Parcelablekotlinx.android.parcel.Parcelize 即使我包含插件 com.android.library 也可以在我的 MPP 模块中工作
  • @Lucho 你是否包含了 ktx(Kotlin android 扩展) - parcelize 是其中的一部分
  • 是的,不幸的是我做了
  • @Lucho 请看这里,这是我的多平台项目,使用 parcelize,所有工作 - 在这里为 common 构建文件,github.com/dmitrish/kinsight-multiplatform/blob/master/…,你也可以查看整个项目(虽然它很漂亮大的)。一些细节是关闭的,原则是可靠的,对我有用
  • 在对 gradle 脚本进行了一些调整后,我现在可以正常工作了,谢谢帮助!我不会将此设置为答案,因为最初的问题是如何让它与序列化一起使用,不过我会给你一个 +1
【解决方案2】:
  1. 新的 Kotlinx Serializable:

    • 此库旨在用于在您的应用与其后端(云服务器)之间传输数据,不适用于在 Android 应用中传输数据。请参阅官方回答 here

  1. 旧的 Java SerializableAndroid Parcelable

    • Java SerializableAndroid Parcelable 慢,请参阅 thisthis

    • Kotlin Parcelize 插件简化了 Android Parcelable 的设置,请参阅 this。只需要注释并从中扩展(被safe args 识别为Custom Parcelable)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多