You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Parcelable扩展异常:SavedStateHandle存储API结果失败

问题原因分析

你遇到的问题核心是:Kotlin标准库的Result类仅实现了Serializable,而非Parcelable。尽管你的DataResult和MyData都实现了Parcelable,但当系统尝试序列化DataResult中的Result<List<MyData>>时,会因为Result是Serializable类型,转而使用Java的序列化机制处理其内部的List<MyData>。而MyData只实现了Parcelable(它不是Serializable的子类),Java序列化无法识别,因此抛出NotSerializableException。

解决方案

下面提供几种可行的修复方案:

方案1:让MyData同时实现Serializable接口

最简单的修改方式,给MyData加上Serializable实现,让Java序列化机制能正常处理它:

@Parcelize
data class MyData(
    val id: String,
    val name: String,
    val phone: String,
    val photo: String? = null
) : Parcelable, Serializable // 新增Serializable接口

@Parcelize
data class DataResult(
    val result: Result<List<MyData>>?,
) : Parcelable

方案2:自定义Parcelable版的Result密封类

避免依赖Kotlin标准库的Result,自己实现一个支持Parcelable的结果密封类,确保整个序列化链路都用Parcelable机制:

// 自定义Parcelable的Result密封类
sealed class ParcelableResult<out T> : Parcelable {
    data class Success<out T>(val data: T) : ParcelableResult<T>()
    data class Failure(val exception: Throwable) : ParcelableResult<Nothing>()

    @Parcelize
    constructor(parcel: Parcel) : this()

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        when (this) {
            is Success -> {
                parcel.writeInt(0)
                parcel.writeParcelable(data as Parcelable, flags) // 泛型需为Parcelable类型
            }
            is Failure -> {
                parcel.writeInt(1)
                parcel.writeSerializable(exception) // Throwable本身实现了Serializable
            }
        }
    }

    companion object CREATOR : Parcelable.Creator<ParcelableResult<*>> {
        override fun createFromParcel(parcel: Parcel): ParcelableResult<*> {
            return when (parcel.readInt()) {
                0 -> Success(parcel.readParcelable(MyData::class.java.classLoader) as List<MyData>)
                1 -> Failure(parcel.readSerializable() as Throwable)
                else -> throw IllegalArgumentException("无效的ParcelableResult类型")
            }
        }

        override fun newArray(size: Int): Array<ParcelableResult<*>?> {
            return arrayOfNulls(size)
        }
    }
}

// 修改DataResult使用自定义的ParcelableResult
@Parcelize
data class DataResult(
    val result: ParcelableResult<List<MyData>>?,
) : Parcelable

方案3:拆分结果状态,直接存储数据

如果不需要保留Result的包装,也可以将成功/失败状态和数据分开存储在SavedStateHandle中,避免嵌套序列化的问题:

class MyViewModel(savedState: SavedStateHandle): ViewModel(){
    private val savedState = savedState

    // 存储成功数据
    val successData = savedState.getLiveData<List<MyData>?>("successData", null)
    // 存储错误信息(可选)
    val errorMessage = savedState.getLiveData<String?>("errorMessage", null)

    // 使用示例:API请求后更新状态
    fun handleApiResult(result: Result<List<MyData>>) {
        result.onSuccess { data ->
            successData.value = data
            errorMessage.value = null
        }.onFailure { e ->
            successData.value = null
            errorMessage.value = e.message
        }
    }
}

内容的提问来源于stack exchange,提问作者Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:43:12