在 Andorid 项目遇到了一个比较诡异而隐蔽的 bug: 使用网络请求获取一个数据,在测试环境中表现一切正常,而在正式包中这个获取的数据却一直为 null。
在测试环境中数据正常,说明我写的代码没问题,但是为啥在正式环境中数据就空了呢?
我从两个方面进行了分析:
这个获取数据的过程分为两步。第一步是网络请求获得 JSON 数据,第二步是把获得的 JSON 数据使用 Gson 转换成 Java Bean。看日志发现网络请求是正常的,问题肯定出现在把 JSON 数据转换成 Java Bean 的过程中。
从测试包和正式包的区别这个角度去思考。两个包的差别在于使用的签名不同,且正式包使用了代码混淆、资源压缩优化。
不断调试测试,最后发现是我把 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 ----------
其中倒数第二行是不混淆需要进行 JSON 转换的实体 Java Bean 。
Java Bean 是不能被混淆的,因为 Java Bean 的属性名必须与 JSON 的 key 一一对应(大小写都必须一样) Gson 才能正常解析,而混淆后 Java Bean 的属性名都变成了 a、b、c 、d,这就导致了转换后的 Java Bean 属性为 null 。
所以要把上面的混淆脚本中最后一句换成自己项目中 Java Bean 的目录。
按功能模块划分包路径时,Java Bean 的位置不能乱放。最好把所有的 Java Bean 都放一块,这样在混淆文件中比较好配置。
这次得到的教训是:常用的类库一定要熟悉,要看官方文档。