版本更新
在版本更新的场景中,需要注意由于某些修改造成的问题。
数据持久化
对于持久化数据结构的更改,需要特别注意,否则可能造成比较严重的问题。比如说SharedPreferences中,如果上个版本某个持久化变量为某一类型(Boolean,String等),在下个版本如果由于业务需求,要注意不要直接更改该变量的类型,最好新增一个变量,否则会崩溃。
多Module
模块间compileOnly
考虑一种场景:
module_a中的构建脚本中有一行代码,这行代码会在其module内的BuildConfig生成一个TEST_VALUE常量:
1 | buildConfigField "String", "TEST_VALUE", '"testtest"' |
将module_a打包成aar,在module_b中通过compileOnly引用它,然后在module_b中打印module_a的BuildConfig.TEST_VALUE的值:
1 | Log.d("LLL", "value = ${BuildConfig.TEST_VALUE}") |
接着将module_a中的上行代码改成:
1 | buildConfigField "String", "TEST_VALUE", '"testtesttest"' |
app module通过implementation引用module_a模块,打包安装apk,发现module_b中打印的值为:value = testtest
。
疑问:
module_b引用module_a aar包的方式是compileOnly,那么这个aar不会被打包进apk,而app module通过implementation方式引用了module_a,那么module_b中调用aar的代码最终调用的应该是module_a中的源码,按理来说打印的内容应该是value = testtesttest
。
于是我将apk反编译了以下,看到在module_a的BuildConfig.smali代码中有一行:
1 | .field public static final TEST_VALUE:Ljava/lang/String; = "testtesttest" |
这说明打包进apk的确实是testtesttest
,那么为啥module_b中会打印value = testtest
呢? 于是我接着看了一下打印的smali代码:
1 | const-string v0, "LLL" |
结论:
在编译期的时候,这行引用了BuildConfig.TEST_VALUE的直接被编译成常量了,仔细一想也确实符合逻辑…,如果这个TEST_VALUE不是static final
类型的常量,就不会出现这种问题,当时碰到问题的时候没有朝这个方向考虑,知道了原因那么就可以解决这个问题了:module_b中不直接通过BuildConfig.TEST_VALUE引用,而是在module_a中增加一个方法,其返回值为BuildConfig.TEST_VALUE,在module_b中通过调用这个方法来获取BuildConfig.TEST_VALUE的值。