计时器崩溃与片段内的KotlinNullPointerException

时间:2017-10-16 15:25:13

标签: android kotlin

我用这种方式在Kotlin中创建了Timer(java.util.Timer):

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    buttonStart.setOnClickListener({
        val timer = Timer("schedule", true)
        timer.scheduleAtFixedRate(1000, 1000) {
            if (timerViewModel?.timerValue?.value!! > 0){
                timerViewModel?.timerValue?.value = timerViewModel?.timerValue?.value!! - 1
                activity.runOnUiThread { textViewTimer.text = timerViewModel?.timerValue?.value?.toString() }
            } else {
                cancel()
            }
        }
    })
}

此代码在第5行崩溃并出现错误:

 kotlin.KotlinNullPointerException
           at com.dmitry.timer.views.TimerFragment$onViewCreated$1$$special$$inlined$scheduleAtFixedRate$1.run(Timer.kt:145)
           at java.util.Timer$TimerImpl.run(Timer.java:284)

当我在activity内创建计时器时 - 它工作正常。 有什么问题?

2 个答案:

答案 0 :(得分:0)

我认为textViewTimeractivity在此行中为空:

activity.runOnUiThread{...}

您确定已正确设置吗?

特别是,您不能依赖Fragment.getActivity()(Kotlin中仅activity)在创建后的任意点返回非空值。因为您在计时器中执行此操作,getActivity可能会返回null。

除此之外:使用这样的嵌套lambda时,堆栈跟踪可能会造成混淆。仔细看看

at com.dmitry.timer.views.TimerFragment$onViewCreated$1$$special$$inlined$scheduleAtFixedRate$1.run(Timer.kt:145)

您可以在$1之后看到scheduleAtFixedRate。那个美元符号表示法通常用于表示匿名方法或lambdas,在这里我认为它指的是你的计时器处理程序本身。

答案 1 :(得分:0)

除了Myk Willis的答案之外,您正在组合安全呼叫(.?)以及NPE呼叫(!!)运营商。

这意味着如果timerViewModeltimerViewModel.timerValuetimerViewModel.timerValue.valuenull,那么这也会导致您看到的NPE。有效地否定了使用安全呼叫运营商的好处。