Kotlin中ModelMapper映射后AWPainting参数值丢失问题
问题根源
你遇到的awPainting值被覆盖的问题,核心原因是**AWPainting是Kotlin的object单例类**,而AWThought中默认将painting属性指向这个唯一的单例实例。
当ModelMapper执行thought.map(AWThought::class.java)时,它会自动初始化AWThought的所有属性,包括painting。由于painting是单例对象,ModelMapper会直接修改这个单例内部的字段(比如id),将其重置为类定义时的默认值0——而你传入的awPainting参数本质上就是这个单例,所以映射后它的id自然变成了0,表现为background00000。
验证逻辑
你可以在映射前后打印awPainting === AWPainting,结果一定是true,说明两者是同一个对象。映射时ModelMapper修改了单例的状态,导致参数值被篡改。
解决方案
方案1:将AWPainting从单例改为普通类(推荐)
单例不适合作为数据载体(尤其是需要多个不同实例的场景),把object改成class,每次创建独立实例:
// 去掉object,改成class class AWPainting: Serializable { var id: Int = 0 var author: String = "" var authorEmail: String = "" var url: String = "" var filename: String = "" var active: Int = 0 var thoughtId: Int = 0 // 原init方法可调整为构造函数或依赖注入方式初始化 constructor() {} constructor(id: Int, author: String, /* 其他参数 */) { this.id = id this.author = author // 赋值其他属性 } // 其余方法保持不变,注意静态相关逻辑需调整 override fun toString(): String { return "background" + String.format(Locale.getDefault(), "%04d", id) } }
同时修改AWThought中painting的默认值:
// 从单例改为创建新实例,或按需初始化 var painting: AWPainting = AWPainting()
这样每个AWPainting实例都是独立的,ModelMapper映射时只会修改当前AWThought对应的实例,不会影响传入的参数。
方案2:配置ModelMapper忽略painting属性的映射
如果必须保留单例,可以让ModelMapper在映射AWThought时跳过painting属性,避免修改单例状态:
// 初始化ModelMapper时添加自定义映射规则 modelMapper.addMappings(object : PropertyMap<AWThoughtDTO, AWThought>() { override fun configure() { skip(destination.painting) // 跳过painting属性的自动映射 } })
这样映射时ModelMapper不会修改painting单例,你后续手动赋值mapThought.painting = awPainting就能保持参数的原有值。
方案3:映射前后保存/恢复单例状态(临时 workaround)
如果暂时无法修改单例结构,可在映射前保存AWPainting的当前状态,映射后恢复:
fun getRandomThought( context: Context?, idLanguage: Int, awPainting: AWPainting, trackId: Int ): AWThought { // 保存单例当前状态 val savedId = AWPainting.id val savedAuthor = AWPainting.author val savedFilename = AWPainting.filename // 保存其他需要保留的字段 val mapAlreadyReadThoughts = mapAll(alreadyReadThoughts, AWThoughtDTO::class.java) val thought = thoughtService.getRandomThought(idLanguage, mapAlreadyReadThoughts) val mapThought = thought.map(AWThought::class.java) // 恢复单例状态 AWPainting.id = savedId AWPainting.author = savedAuthor AWPainting.filename = savedFilename // 恢复其他字段 mapThought.painting = awPainting mapThought.trackId = trackId setThoughtTrackIds(mapThought, trackId) alreadyReadThoughts.add(mapThought) saveAlreadyReadThoughtsList(alreadyReadThoughts, context) return mapThought }
这种方式只是临时解决,不推荐长期使用,因为单例的状态共享会带来其他潜在问题。
内容的提问来源于stack exchange,提问作者Diego Perez

