如何通过Intent从Activity向Service传递对象数组?遇序列化异常
问题根源
报错的核心原因有两点:
- 你使用的
@Serializable是Kotlinx Serialization框架的注解,并非Java标准的java.io.Serializable接口,而bundle.putSerializable仅识别实现了Java Serializable接口的对象。 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字符串传递,再反序列化还原:
- 确保项目已引入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" }
- 修改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) }
- 在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
相关产品推荐
相关产品推荐

