Kotlin中对象字符串转数据类及Fragment间数据类传递方案
如何处理Fragment间数据类传递与toString转数据类的问题
首先得明确说清楚:直接把dataClass.toString()的结果转回数据类是非常不推荐的做法。因为toString()的输出是为了人类可读性设计的,没有统一的标准化格式——一旦你的数据类新增字段、修改字段顺序,或者系统默认的toString()实现有变化,你的解析逻辑就会直接崩溃,维护成本极高。
如果非要硬做,你得自己写解析逻辑,比如用正则表达式匹配每个字段的键值对,嵌套类还要递归解析,但这种方式完全是给自己挖坑,真心不建议。
更优的Fragment间数据类传递方式
Android官方推荐的做法是让数据类实现Parcelable(效率更高)或Serializable接口,这样可以直接通过Bundle传递,完全不需要转成字符串。
方式1:实现Parcelable(推荐)
Parcelable是Android特有的序列化方式,比Serializable快很多,适合在组件间传递数据。需要让你的两个数据类都实现Parcelable:
首先是嵌套的AuctionDetailInfo:
data class AuctionDetailInfo( val AuctionNumber: Int, val AuctionStatus: Int, val InitiatorType: Int ) : Parcelable { // 从Parcel读取数据的构造函数 constructor(parcel: Parcel) : this( parcel.readInt(), parcel.readInt(), parcel.readInt() ) // 写入数据到Parcel override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(AuctionNumber) parcel.writeInt(AuctionStatus) parcel.writeInt(InitiatorType) } override fun describeContents(): Int = 0 // 静态CREATOR对象,用于反序列化 companion object CREATOR : Parcelable.Creator<AuctionDetailInfo> { override fun createFromParcel(parcel: Parcel): AuctionDetailInfo { return AuctionDetailInfo(parcel) } override fun newArray(size: Int): Array<AuctionDetailInfo?> { return arrayOfNulls(size) } } }
然后是外层的InstrumentResponse:
data class InstrumentResponse( val AGM: Boolean, val AllOrNone: Boolean, val Bonus: Boolean, val Dividend: Boolean, val EGM: Boolean, val AuctionDetailInfo: AuctionDetailInfo ) : Parcelable { constructor(parcel: Parcel) : this( // 布尔类型用Byte存储,1为true,0为false parcel.readByte() != 0.toByte(), parcel.readByte() != 0.toByte(), parcel.readByte() != 0.toByte(), parcel.readByte() != 0.toByte(), parcel.readByte() != 0.toByte(), // 读取嵌套的Parcelable对象 parcel.readParcelable(AuctionDetailInfo::class.java.classLoader)!! ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeByte(if (AGM) 1 else 0) parcel.writeByte(if (AllOrNone) 1 else 0) parcel.writeByte(if (Bonus) 1 else 0) parcel.writeByte(if (Dividend) 1 else 0) parcel.writeByte(if (EGM) 1 else 0) parcel.writeParcelable(AuctionDetailInfo, flags) } override fun describeContents(): Int = 0 companion object CREATOR : Parcelable.Creator<InstrumentResponse> { override fun createFromParcel(parcel: Parcel): InstrumentResponse { return InstrumentResponse(parcel) } override fun newArray(size: Int): Array<InstrumentResponse?> { return arrayOfNulls(size) } } }
传递与接收数据
- 源Fragment传递:
// 假设你已经创建了InstrumentResponse实例 val response = InstrumentResponse( AGM = false, AllOrNone = true, Bonus = true, Dividend = true, EGM = false, AuctionDetailInfo = AuctionDetailInfo(0, 0, 0) ) // 放入Bundle val bundle = Bundle().apply { putParcelable("INSTRUMENT_RESPONSE_KEY", response) } // 传递给目标Fragment(比如用FragmentManager或Navigation组件) val targetFragment = TargetFragment() targetFragment.arguments = bundle
- 目标Fragment接收:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val response = arguments?.getParcelable<InstrumentResponse>("INSTRUMENT_RESPONSE_KEY") // 拿到数据后就可以正常使用了 }
方式2:实现Serializable(简单但效率低)
如果觉得Parcelable写起来麻烦,也可以用Serializable,它是Java的标准序列化接口,代码更简洁,但效率不如Parcelable:
// 两个数据类都实现Serializable data class AuctionDetailInfo( val AuctionNumber: Int, val AuctionStatus: Int, val InitiatorType: Int ) : Serializable data class InstrumentResponse( val AGM: Boolean, val AllOrNone: Boolean, val Bonus: Boolean, val Dividend: Boolean, val EGM: Boolean, val AuctionDetailInfo: AuctionDetailInfo ) : Serializable
传递与接收
- 传递:
bundle.putSerializable("INSTRUMENT_RESPONSE_KEY", response)
- 接收:
val response = arguments?.getSerializable("INSTRUMENT_RESPONSE_KEY") as? InstrumentResponse
总结
- 绝对不要用
toString()的输出转回数据类,这种方式既脆弱又难维护; - 优先选择
Parcelable实现组件间数据类传递,效率更高,符合Android最佳实践; - 追求代码简洁的话可以用
Serializable,但要注意它的性能劣势。
内容的提问来源于stack exchange,提问作者Rupesh
相关产品推荐
相关产品推荐

