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
相关产品推荐
相关产品推荐

