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

如何通过Intent从Activity向Service传递对象数组?遇序列化异常

问题根源

报错的核心原因有两点:

  1. 你使用的@Serializable是Kotlinx Serialization框架的注解,并非Java标准的java.io.Serializable接口,而bundle.putSerializable仅识别实现了Java Serializable接口的对象。
  2. LocalDateTime本身未实现Java Serializable接口,即便Item类实现了该接口,依然会因为LocalDateTime无法序列化而抛出异常。

解决方案

方案一:实现Android推荐的Parcelable接口(效率更高)

Parcelable是Android专为跨组件传递对象设计的序列化方式,性能优于Serializable。需要让Item类实现Parcelable接口,并处理LocalDateTime的序列化/反序列化:

修改Item类:

import android.os.Parcel
import android.os.Parcelable
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

data class Item(
    val id: Int,
    val data: LocalDateTime? = LocalDateTime.now(),
    val message: String,
    var isValid: Boolean? = false
) : Parcelable {
    // 从Parcel构造对象
    constructor(parcel: Parcel) : this(
        parcel.readInt(),
        parcel.readString()?.let { LocalDateTime.parse(it, DateTimeFormatter.ISO_LOCAL_DATE_TIME) },
        parcel.readString() ?: "",
        parcel.readValue(Boolean::class.java.classLoader) as? Boolean
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(id)
        // 将LocalDateTime转为字符串写入Parcel
        parcel.writeString(data?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
        parcel.writeString(message)
        parcel.writeValue(isValid)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Item> {
        override fun createFromParcel(parcel: Parcel): Item {
            return Item(parcel)
        }

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

修改Activity中传递数据的代码:

listViewModel.itemList.observe(this) { itemList ->
    listAdapter.setList(itemList)
    recyclerView.adapter = listAdapter
    val intent = Intent(this, FileService::class.java)
    // 将List转为ArrayList(ArrayList实现了Parcelable)
    intent.putParcelableArrayListExtra("data", ArrayList(itemList))
    startService(intent)
}

在Service中接收数据:

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    val itemList = intent?.getParcelableArrayListExtra<Item>("data")
    // 处理业务逻辑
    return super.onStartCommand(intent, flags, startId)
}

方案二:用Kotlinx Serialization转JSON字符串传递

如果不想编写Parcelable的模板代码,可以将对象序列化为JSON字符串传递,再反序列化还原:

  1. 确保项目已引入Kotlinx Serialization依赖(Module级build.gradle):
plugins {
    id 'org.jetbrains.kotlin.plugin.serialization' version '你的Kotlin版本号'
}

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0"
}
  1. 修改Activity传递代码:
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

listViewModel.itemList.observe(this) { itemList ->
    listAdapter.setList(itemList)
    recyclerView.adapter = listAdapter
    val intent = Intent(this, FileService::class.java)
    // 将List序列化为JSON字符串
    val jsonStr = Json.encodeToString(itemList)
    intent.putExtra("data", jsonStr)
    startService(intent)
}
  1. 在Service中解析数据:
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    val jsonStr = intent?.getStringExtra("data")
    jsonStr?.let {
        val itemList = Json.decodeFromString<List<Item>>(it)
        // 处理业务逻辑
    }
    return super.onStartCommand(intent, flags, startId)
}

注意:Item类需保留@Serializable注解:

import kotlinx.serialization.Serializable
import java.time.LocalDateTime

@Serializable
data class Item(
    val id: Int,
    val data: LocalDateTime? = LocalDateTime.now(),
    val message: String,
    var isValid: Boolean? = false
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:15:49