美文网首页
Android 关于 kotlin 局部变量发生变化的问题

Android 关于 kotlin 局部变量发生变化的问题

作者: 雁过留声_泪落无痕 | 来源:发表于2022-05-26 09:02 被阅读0次

现象

class KotlinLocalVariableActivity : BaseActivity() {

    private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val editText = EditText(this)
        setContentView(editText)

        var num = 0
        editText.doOnTextChanged { text, start, before, count ->
            scope.launch {
                Log.d("hehe", "$num. text: $text")
                delay(2000L)
                Log.d("hehe", "$num. text: $text")

                num++
            }
        }
    }

}

无意中发现上述代码在两处打印日志的地方打印出来的值居然不一样,让我一度怀疑局部变量居然能发生变化?

原因

最后排查才发现,每次回调传过来的 text 居然是一个引用值,也就是说当 EditText 发生变化时,text 的值就已经变了,在上一次的回调中如果延时(代码里是 2s)后再去获取 text 的值,就已经是新值了。

想要不变,转成局部变量就可以了,如:

// toString() 不可少
val localText = text.toString()

Smart cast is impossible

测试过程中还发现了 Smart cast is impossible 的问题,也一起记录下.

class TestActivity : BaseActivity() {

    private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val editText = EditText(this)
        setContentView(editText)

        var str: String? = null
        scope.launch {
            str = ""
        }
        if (null != str) {
            val len = str.length
            LogUtils.d("len: $len")
        }
    }

}
image.png

由于协程可能运行在其它线程,所以协程内如果对局部变量进行了赋值,那么局部变量就可能发生变化,所以这里即时进行了 if (null != str) 的判断,由于线程问题,等运行到 str.length 的时候也可能发生空指针。

如果把协程内的 str = "" 注释掉,那么 IDE 则不会提示有问题了。

相关文章

网友评论

      本文标题:Android 关于 kotlin 局部变量发生变化的问题

      本文链接:https://www.haomeiwen.com/subject/ddxyprtx.html