如何向Service传递对象数组?传ArrayList到Service序列化崩溃如何解决
问题根因
从异常栈的底层错误可以定位到问题根源:android.location.Location 系统类本身没有实现 Serializable 接口,即使你的自定义 MyItem 声明实现了 Serializable,序列化传输过程中遍历到内部的 Location 属性时,仍然会抛出序列化失败异常。
修复方案
方案1:抽取Location所需字段独立存储
不直接存储 Location 对象,将业务需要用到的Location属性(经度、纬度、精度、时间戳等基础类型)单独抽出来存在 MyItem 中,基础数据类型本身默认支持序列化:
// 修改后的数据类定义 data class MyItem( val latitude: Double, val longitude: Double, val accuracy: Float, var time:Long = 0 ): Serializable // 构造MyItem实例时从Location对象取对应字段 val myItem = MyItem( latitude = location.latitude, longitude = location.longitude, accuracy = location.accuracy, time = System.currentTimeMillis() )
方案2:使用Android原生Parcelable实现序列化(推荐)
Parcelable是Android平台专有的序列化方案,性能远高于Serializable,且系统Location类本身已经实现了Parcelable接口,直接适配即可:
- 首先在模块级build.gradle中开启kotlin-parcelize插件:
plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id 'kotlin-parcelize' // 新增这行 } - 修改MyItem实现Parcelable:
import android.os.Parcelable import kotlinx.parcelize.Parcelize import android.location.Location @Parcelize data class MyItem(val location:Location, var time:Long = 0): Parcelable - 传输时使用Parcelable专属的put方法:
private var listOfMyItems:ArrayList<MyItem> = arrayListOf() val i = Intent(context, MyService::class.java) i.putParcelableArrayListExtra("list", listOfMyItems) context.bindService(i, getConnectionObject(), Context.BIND_AUTO_CREATE) context.startService(i) - Service中读取数据:
override fun onBind(intent: Intent?): IBinder? { val list = intent?.getParcelableArrayListExtra<MyItem>("list") list?.let { val targetList: ArrayList<MyItem> = it.toCollection(ArrayList()) // 后续业务逻辑 } return null }
注意事项
- 避免使用强制类型转换
as,配合Kotlin空安全语法处理可降低崩溃风险 - 若你在
onStartCommand中也需要读取Intent数据,需使用同样的Parcelable读取逻辑
内容的提问来源于stack exchange,提问作者Paweł Mańczak
相关产品推荐
相关产品推荐

