用Kotlin进行Android开发时,单例模式也是用得比较多的场景。由于Kotlin中没有static关键字,创建类的单例一般会使用Companion objct来进行创建。代码如下:
class BleApi private constructor(){ private object BleApiHolder{ val instance = BleApi() } companion object { @JvmStatic val instance:BleApi get() = } }
在Java中我们可以调用()来获取BleApi单例
在Kotlin中我们可以调用()来获取BleApi单例
如果代码不进行混淆的话,那么以上使用是不会出问题的,但如果要对代码进行混淆,那么你会发现Kotlin中调用不了instance来获取到BleApi。
我们混淆代码如下
-keep class { *; }
What?不是已经排除了BleApi的类不混淆了么。But,我们是按Java的规则在混淆啊。所以悲剧就产生了,在混淆时混淆器还是会将Companion object进行混淆,由于我们注解了@JvmStatic,这个相当于Java中的static,所以在Java中使用是不会出现问题的。但在Kotlin 中,就呵呵了!
既然找到了原因,那我们就想办法来处理。
打开BleApi类,打开Tools->Kotlin->Show Kotlin Bytecode。我们可以看到Kotlin生成的Bytecode的代码。可以看到生成有个类public final class com/calm/comm/lib/ble/BleApi$Companion,原来Kotlin的Companion object会生成这个类,那么我们可以-keep掉这个类不被混淆就可以解决这个问题了。
So,在混淆代码加入如下语句:
-keep class $Companion{ *; }
然后在用Kotlin测试调用()就没有问题了。