0%

Android开发踩坑合集

版本更新

在版本更新的场景中,需要注意由于某些修改造成的问题。

数据持久化

对于持久化数据结构的更改,需要特别注意,否则可能造成比较严重的问题。比如说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
2
3
const-string v0, "LLL"
const-string v1, "value = testtest"
invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

结论:

在编译期的时候,这行引用了BuildConfig.TEST_VALUE的直接被编译成常量了,仔细一想也确实符合逻辑…,如果这个TEST_VALUE不是static final类型的常量,就不会出现这种问题,当时碰到问题的时候没有朝这个方向考虑,知道了原因那么就可以解决这个问题了:module_b中不直接通过BuildConfig.TEST_VALUE引用,而是在module_a中增加一个方法,其返回值为BuildConfig.TEST_VALUE,在module_b中通过调用这个方法来获取BuildConfig.TEST_VALUE的值。