场景
最近要用kotlin写一个每隔一段时间切视频并截图
刷刷的就写出来了,很快啊
timerTask = object : TimerTask() {
override fun run() {
captureWindow()
if ((group + 1) * 4 >= urls.size) {
showDialog()
timerTask.cancel()
timer.cancel()
}
group++
updatePlayers()
}
}
timer = Timer()
timer.schedule(timerTask, 15000, 15000)
结果一运行就闪退了
Player is accessed on the wrong thread
java.lang.IllegalStateException: Player is accessed on the wrong thread.
Current thread: 'Timer-0'
Expected thread: 'main'
https://developer.android.com/media/media3/exoplayer/hello-world#a-note-on-threading
它意思是 Exoplayer 的实例必须从主线程访问,但是呢,我们现在是在定时器子线程(Timer-0)内部访问的
一直和单线程 js 打交道的人生,哪里懂得什么主线程子线程/(ㄒoㄒ)/~~
思路一
如果让子线程发送 Event 到主线程,由主线程响应,然后主线程去操作 Exoplayer,不就好了吗
悲伤的是,AI 写的代码驴头不对马嘴,只能自己去官方文档上现学。
https://kotlinlang.org/api/latest/jvm/stdlib/org.w3c.dom.events/-event-target/
结果搜了半天,发现唯一与 Event 有关的是“活动”
kotlin 好像和 js 这种不大一样,js 的核心就是处理事件和响应事件,但是 kotlin 不是为这方面设计的
不过我觉得往这个方向没问题,可能需要学习协程相关的吧
思路二
虽然没有 setInterval,但是 kotlin 是有等效于 setTimeout 的方法的
android.os.Handler 可以实现过一段事件执行某段代码
Handler(Looper.getMainLooper()).postDelayed(
{
captureWindow()
if ((group + 1) * 4 >= urls.size) {
showDialog()
}
group++
updatePlayers()
},
15000
)
接着发挥传统艺能把 setTimeout 改写为 setInterval
private fun updateEvery15s() {
fun mySetTimeout() {
Handler(Looper.getMainLooper()).postDelayed(
{
captureWindow()
if ((group + 1) * 4 >= urls.size) {
showDialog()
} else {
group++
updatePlayers()
mySetTimeout()
}
},
if (group == 0) 20000 else 15000
)
}
mySetTimeout()
}
完成!