引言
Gson是不是很簡(jiǎn)潔很容易上手呢?最主要的就兩個(gè)方法toJson()和fromJson()將實(shí)體轉(zhuǎn)為Json和將Json轉(zhuǎn)為實(shí)體嗤军。
我之前沒(méi)有使用過(guò)Gson,更不用說(shuō)是用Kotlin了晃危。由于使用的時(shí)間還不是很長(zhǎng)叙赚,好不好用還真不好說(shuō)。
我之前用慣了Json且有這個(gè)JsonHelper工具類(lèi)的幫助僚饭,暫時(shí)性的認(rèn)為沒(méi)有JsonHelper好用且功能不如JsonHelper的實(shí)用震叮。
主要是因?yàn)榕龅搅讼挛膶⒁v述的坑。
正文
我在編寫(xiě)項(xiàng)目的過(guò)程中鳍鸵,需要將一些暫時(shí)性的數(shù)據(jù)進(jìn)行保存苇瓣,自然而然的就想到了之前創(chuàng)建的SpUtils類(lèi)將數(shù)據(jù)存儲(chǔ)在SharedPreferences中。
于是寫(xiě)了兩個(gè)方法偿乖,完美實(shí)現(xiàn)需求
fun <T> getObject(key: String, cls: Class<T>): T {
var value = getString(key, "")
return gson.fromJson<T>(value, cls)
}
fun setObject(key: String, obj: Any) {
var value = gson.toJson(obj)
setString(key, value)
}
思路主要是將實(shí)體轉(zhuǎn)換成Json字符串保存击罪,需要時(shí)取出Json字符串并序列化成實(shí)體返回。
這時(shí)需求升級(jí)了贪薪,需要保存一個(gè)列表媳禁。
fun <T> getList(key: String, cls: Class<T>): List<T> {
var value = getString(key, "")
if (TextUtils.isEmpty(value)) {
return ArrayList()
}
return gson.fromJson(value, object : TypeToken<List<T>>() {}.type)
}
這時(shí)看著沒(méi)毛病吧,程序也能夠正常的編譯画切,但運(yùn)行到取實(shí)體的變量時(shí)卻崩潰了
類(lèi)型轉(zhuǎn)換失斂⒒?霍弹?為什么呢毫别??debug走一遍
問(wèn)題出現(xiàn)了典格,原本List里面包含的對(duì)象岛宦,經(jīng)過(guò)一遍存儲(chǔ)和取出,List里卻變成了鍵值對(duì)耍缴。
可以得出結(jié)論Gson并沒(méi)有序列化成功砾肺。
費(fèi)了不少心思齐佳,搜尋了很多資料,終于明白了债沮。原因是java的類(lèi)型擦除
Java中的泛型基本上都是在編譯器這個(gè)層次來(lái)實(shí)現(xiàn)的炼吴。在生成的Java字節(jié)碼中是不包含泛型中的類(lèi)型信息的。使用泛型的時(shí)候加上的類(lèi)型參數(shù)疫衩,會(huì)在編譯器在編譯的時(shí)候去掉硅蹦。這個(gè)過(guò)程就稱(chēng)為類(lèi)型擦除。
https://segmentfault.com/q/1010000009644038
由于我是用了泛型闷煤,導(dǎo)致fromJson()只知道是List而里面的類(lèi)型卻是未知的童芹,因此返回成了鍵值對(duì)。
所以這里采用傳遞type的方式鲤拿,否則會(huì)因?yàn)檎也坏筋?lèi)型假褪,而序列化失敗
fun <T> getList(key: String, type: Type): T {
var value = getString(key, "")
return gson.fromJson(value, type)
}
SpUtils.getList<List<Category>>(KEY_CATEGORY_LIST, object : TypeToken<List<Category>>() {}.type)
從這一點(diǎn)看之前的JsonHelper就不會(huì)有這種問(wèn)題。
不能一棍子打死近顷,我還是抱著學(xué)習(xí)的態(tài)度繼續(xù)深入生音。