在 Andorid 項目遇到了一個比較詭異而隱蔽的 bug: 使用網(wǎng)絡請求獲取一個數(shù)據(jù),在測試環(huán)境中表現(xiàn)一切正常村砂,而在正式包中這個獲取的數(shù)據(jù)卻一直為 null烂斋。
在測試環(huán)境中數(shù)據(jù)正常,說明我寫的代碼沒問題础废,但是為啥在正式環(huán)境中數(shù)據(jù)就空了呢汛骂?
我從兩個方面進行了分析:
這個獲取數(shù)據(jù)的過程分為兩步。第一步是網(wǎng)絡請求獲得 JSON 數(shù)據(jù)评腺,第二步是把獲得的 JSON 數(shù)據(jù)使用 Gson 轉(zhuǎn)換成 Java Bean帘瞭。看日志發(fā)現(xiàn)網(wǎng)絡請求是正常的蒿讥,問題肯定出現(xiàn)在把 JSON 數(shù)據(jù)轉(zhuǎn)換成 Java Bean 的過程中蝶念。
從測試包和正式包的區(qū)別這個角度去思考抛腕。兩個包的差別在于使用的簽名不同,且正式包使用了代碼混淆媒殉、資源壓縮優(yōu)化担敌。
不斷調(diào)試測試,最后發(fā)現(xiàn)是我把 Java Bean 放錯了位置(或者說是 Gson 混淆配置不正確)而引起的問題廷蓉。
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }
##---------------End: proguard configuration for Gson ----------
其中倒數(shù)第二行是不混淆需要進行 JSON 轉(zhuǎn)換的實體 Java Bean 全封。
Java Bean 是不能被混淆的,因為 Java Bean 的屬性名必須與 JSON 的 key 一一對應(大小寫都必須一樣) Gson 才能正常解析桃犬,而混淆后 Java Bean 的屬性名都變成了 a售貌、b、c 疫萤、d,這就導致了轉(zhuǎn)換后的 Java Bean 屬性為 null 敢伸。
所以要把上面的混淆腳本中最后一句換成自己項目中 Java Bean 的目錄扯饶。
按功能模塊劃分包路徑時,Java Bean 的位置不能亂放池颈。最好把所有的 Java Bean 都放一塊尾序,這樣在混淆文件中比較好配置。
這次得到的教訓是:常用的類庫一定要熟悉躯砰,要看官方文檔每币。