IllegalArgumentException
总结
使用 lambda + livedata 时,lambda 对象有可能单例,导致多次 observe() 方法报错。
现象
从 observe() 源码可以看出它是由于一个 observer 监听了多个 lifecycle。正常情况下不会出现,但如果使用了 kotlin 的 lambda 表达式就有可能出现。
原因
kotlin 中的 lambda 最终都会转换成一个对象,一般情况下每一次使用 lambda 都会生成不同的对象,但如果该类不依赖某个具体对象,kotlin 就使用单例模式实现该类,从而每一个 lambda 都是同一个对象。比如对下面的方法
liveData.observe(this@MainActivity){
// 什么都不做
// 或者直接使用 log 输出一个固定字符串
// 两者效果一样
}
liveData.observe(this@MainActivity){
// testStr 是 MainActivity 中的一个成员变量
Log.e(TAG, testStr)
}
看一下第一个 observe() 对应的 smali 代码
// MainActivity$$ExternalSyntheticLambda2 就是第一个 lambda 对应的类
// 这里直接读取 INSTANCE 字段
sget-object v2, Lcom/example/demo/MainActivity$$ExternalSyntheticLambda2;->INSTANCE:Lcom/example/demo/MainActivity$$ExternalSyntheticLambda2;
看一下 ExternalSyntheticLambda2 的主要逻辑
可以看出空 lambda 对象就是单例的
第二个 observer 对应的 smali 如下,可以看到是标准的 new 对象流程,所以不会存在多次 observe() 时 observer() 相同的情况。
// 标准的构建对象指令
new-instance v2, Lcom/example/demo/MainActivity$$ExternalSyntheticLambda1;
invoke-direct {v2, p0}, Lcom/example/demo/MainActivity$$ExternalSyntheticLambda1;-><init>(Lcom/example/demo/MainActivity;)V