定时器崩溃KotlinNullPointerException内部片段
我以这种方式在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() } } }) }
此代码在第五行崩溃,错误:
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
创建计时器 – 它工作正常。 问题是什么?
它看起来像我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)
您可以在scheduleAtFixedRate
之后看到$1
。 美元符号表示法经常用来指代匿名方法或lambda表达式,在这里我相信它是指你的定时器处理程序本身。
除了Myk Willis的回答之外,您还将安全呼叫( .?
)以及NPE呼叫( !!
)操作员组合在一起。
这意味着,如果timerViewModel
, timerViewModel.timerValue
或timerViewModel.timerValue.value
为null
那么也可以导致你看到的NPE。 有效地否定使用安全呼叫运营商的好处。