我用这种方式在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
内创建计时器时 - 它工作正常。
有什么问题?
答案 0 :(得分:0)
我认为textViewTimer
或activity
在此行中为空:
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呼叫(!!
)运营商。
这意味着如果timerViewModel
,timerViewModel.timerValue
或timerViewModel.timerValue.value
为null
,那么这也会导致您看到的NPE。有效地否定了使用安全呼叫运营商的好处。