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

Android保存含Pair值的Connection ArrayList遇NotSerializableException问题

问题描述

尝试将包含Pair类型值的Connection对象ArrayList保存到文件时,抛出NotSerializableException异常。已让Connection类实现Serializable接口,推测异常由Pair的泛型参数或关联类引发,需实现该列表的保存与读取功能。


相关代码

Connection.kt

data class Connection(
//    @Transient
    var firstPair: Pair<CircuitComponent, Int>,
//    @Transient
    var secondPair: Pair<CircuitComponent, Int>
) : Serializable{

    var pathOfLine: NamedPath = NamedPath("")

    data class State(
        val firstComponentCode: String,
        val secondComponentCode: String,
        val firstTouchPointIndex: Int,
        val secondTouchPointIndex: Int,
        val pathName: String,
    ): Serializable


     fun getState() = State(
        firstPair.first.getCode(),
        secondPair.first.getCode(),
        firstPair.second,
        secondPair.second,
        pathOfLine.name
    )
}

保存Connection ArrayList的代码

val projectsDirectory = File("${requireActivity().filesDir}/projects")
projectsDirectory.mkdir()
val thisProjectDirectory = File("${projectsDirectory}/${args.project.customerName}")
thisProjectDirectory.mkdir()
val file = File(thisProjectDirectory, "/image.jpg")
val out = FileOutputStream(file)
args.project.image = file.absolutePath
args.project.dateModified = SimpleDateFormat("MMMM dd yyyy", Locale.getDefault()).format(Date())
args.project.size = "${thisProjectDirectory.length() / 1000} kb"
serialize(thisProjectDirectory.absolutePath,"list_con.ser", connectionsList)
designBitmap.compress(Bitmap.CompressFormat.JPEG, 50, out)
out.close()

序列化方法

fun serialize(location:String,fileName:String,obj:Any){
 val fileOutputStream = FileOutputStream("$location/$fileName")
 val objectOutputStream = ObjectOutputStream(fileOutputStream)
 objectOutputStream.writeObject(obj)
 objectOutputStream.close()
}

读取Connection ArrayList的代码

val projectLocation = "${requireActivity().filesDir}/projects/${args.project.customerName}"
val projectDirectory = File(projectLocation)
val connectionsList= deserialize(File(projectDirectory , "list_con.ser"))

反序列化方法

fun deserialize(file: File): Any? {
    val fileInputStream = FileInputStream(file)
    val objectInputStream = ObjectInputStream(fileInputStream)
    return objectInputStream.readObject()
}

解决方案

方案1:确保所有关联类实现Serializable接口

Kotlin的Pair类本身已实现Serializable,但它的泛型参数必须也能序列化才不会抛出异常。需完成以下修改:

  • 让CircuitComponent类实现Serializable:
    class CircuitComponent : Serializable {
        // 原有类逻辑,如getCode方法
        fun getCode(): String {
            // 你的实现
        }
    }
    
  • 让NamedPath类实现Serializable:
    class NamedPath(val name: String) : Serializable {
        // 原有类逻辑
    }
    

修改完成后,原有的序列化/反序列化代码即可正常运行。

方案2:用自定义State类中转序列化

如果无法修改CircuitComponent或NamedPath使其序列化,可利用Connection中已定义的State类(已实现Serializable)间接保存:

修改保存逻辑

将Connection列表转换为State列表后再序列化:

// 替换原有的serialize调用
val stateList = connectionsList.map { it.getState() }
serialize(thisProjectDirectory.absolutePath, "list_con.ser", stateList)

修改读取逻辑

读取State列表后重建Connection对象:

val projectLocation = "${requireActivity().filesDir}/projects/${args.project.customerName}"
val projectDirectory = File(projectLocation)
val stateList = deserialize(File(projectDirectory, "list_con.ser")) as List<Connection.State>
// 从State重建Connection,需给CircuitComponent添加根据code重建的方法
val connectionsList = stateList.map { state ->
    Connection(
        Pair(CircuitComponent.fromCode(state.firstComponentCode), state.firstTouchPointIndex),
        Pair(CircuitComponent.fromCode(state.secondComponentCode), state.secondTouchPointIndex)
    ).apply {
        pathOfLine = NamedPath(state.pathName)
    }
}

注:需给CircuitComponent添加fromCode静态方法,用于通过保存的code字符串重建对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:45:25