系列文章全部為本人的學(xué)習(xí)筆記,若有任何不妥之處谴蔑,隨時(shí)歡迎拍磚指正豌骏。如果你覺得我的文章對(duì)你有用,歡迎關(guān)注我以及我的Kotlin專題树碱,我們一起學(xué)習(xí)進(jìn)步肯适!
終于有一篇Kotlin文章不是沿襲了之前的筆記系列,這是嘗試將Kotlin用到項(xiàng)目中遇到的第一個(gè)問題:如何將Kotlin中的泛型進(jìn)行序列化成榜?這個(gè)問題我們分兩步解決:
- 一般數(shù)據(jù)類(
data class
)的序列化 - 泛型的序列化
一框舔、一般數(shù)據(jù)類(data class
)的序列化
這個(gè)問題在我之前的文章《Kotlin學(xué)習(xí)筆記(9)- 數(shù)據(jù)類》中提到過,這里再說一下,在kotlin中序列化的實(shí)現(xiàn)方法和java中的手動(dòng)實(shí)現(xiàn)基本一致
data class PersonData(var name : String, var age : Int, val sex : String) : Parcelable{
override fun writeToParcel(p0: Parcel?, p1: Int) {
p0?.writeString(this.name)
p0?.writeInt(this.age)
p0?.writeString(this.sex)
}
override fun describeContents(): Int {
return 0
}
constructor(source: Parcel) : this(source.readString(), source.readInt(), source.readString())
companion object {
@JvmField val CREATOR: Parcelable.Creator<PersonData> = object : Parcelable.Creator<PersonData> {
override fun createFromParcel(source: Parcel): PersonData {
return PersonData(source)
}
override fun newArray(size: Int): Array<PersonData?> {
return arrayOfNulls(size)
}
}
}
}
值得一提的是刘绣,在我寫《Kotlin學(xué)習(xí)筆記(9)- 數(shù)據(jù)類》的時(shí)候樱溉,也確實(shí)只能這么寫。但是現(xiàn)在AS上已經(jīng)有了自動(dòng)序列化的插件:在AS的Settings中選擇Plugins纬凤,然后搜索“Parcelable Code Generator(for kotlin)”福贞,安裝即可。相信很多朋友用過它的Andorid版停士,使用方法基本是一樣的挖帘,使用效果如圖:
二、泛型的序列化
泛型就不必多說了恋技,我在《Kotlin學(xué)習(xí)筆記(10)- 泛型》也詳細(xì)的講過了(這廣告太自然了拇舀,哇咔咔),個(gè)人使用最多的場(chǎng)景應(yīng)該就是處理服務(wù)器返回的結(jié)果了吧蜻底。如果恰巧這個(gè)結(jié)果模型需要在Activity間傳遞骄崩,那么是不是就要考慮泛型的序列化了呢?首先看看我是怎么實(shí)現(xiàn)的:
data class Resp<T: Parcelable>(var code: Int = 0,
var msg: String = "",
var data: T? = null)
: Parcelable {
val EMPTY = "empty"
constructor(source: Parcel) : this() {
code = source.readInt()
msg = source.readString()
val className = source.readString()
data = if(className == EMPTY) null else source.readParcelable(Class.forName(className).getClassLoader())
}
fun classLoader() : ClassLoader {
val type = javaClass.genericSuperclass
val params = (type as ParameterizedType).actualTypeArguments
return (params[0] as Class<T>).classLoader
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(this.code)
dest.writeString(this.msg)
dest.writeString(if(this.data==null) EMPTY else this.data!!::class.java.name)
dest.writeParcelable(this.data, flags)
}
companion object {
@JvmField val CREATOR: Parcelable.Creator<Resp<Parcelable>> = object : Parcelable.Creator<Resp<Parcelable>> {
override fun createFromParcel(source: Parcel): Resp<Parcelable> {
return Resp<Parcelable>(source)
}
override fun newArray(size: Int): Array<Resp<Parcelable>?> {
return arrayOfNulls(size)
}
}
}
}
要注意以下幾點(diǎn):
泛型
T
一定要顯式的聲明可序列化薄辅,也就是我的泛型類型<T: Parcelable>
要拂。數(shù)據(jù)流的聲明參數(shù)中,泛型參數(shù)一定要有默認(rèn)值站楚,通常是默認(rèn)
null
脱惰。我的習(xí)慣是全部參數(shù)都給默認(rèn)值,這樣可以有一個(gè)無參的構(gòu)造函數(shù)窿春。-
我們通過保存泛型類型的方式枪芒,來達(dá)到無法獲取泛型的
ClassLoader
的問題。也就是這篇文章的最重要的點(diǎn):constructor(source: Parcel) : this() { ... val className = source.readString() data = if(className == EMPTY) null else source.readParcelable(Class.forName(className).getClassLoader()) } override fun writeToParcel(dest: Parcel, flags: Int) { ... dest.writeString(if(this.data==null) EMPTY else this.data!!::class.java.name) dest.writeParcelable(this.data, flags) }