Android项目出现Animators只能在Looper线程运行的报错求助
嘿,我一眼就看出问题所在啦!你遇到的android.util.AndroidRuntimeException: Animators may only be run on Looper threads错误,根源是你在非主线程(IO线程)里做了UI操作。
具体来说,你的addToFav方法用GlobalScope.launch(Dispatchers.IO)启动了一个IO线程,然后在这个线程里直接调用binding.imgToolbarBtnFav.setBackgroundResource()——Android的UI组件更新(包括设置背景资源,这个操作可能涉及到View的动画或状态变更)必须在**主线程(也就是绑定了Looper的线程)**执行,IO线程没有Looper,自然就触发这个报错了。
给你两个关键修复步骤:
1. 把UI操作切回主线程
在IO线程里完成数据库操作后,用withContext(Dispatchers.Main)把更新UI的代码包裹起来,强制切换到主线程执行:
2. 替换不安全的GlobalScope
GlobalScope的生命周期不受Activity控制,容易引发内存泄漏,推荐用和Activity生命周期绑定的lifecycleScope,更安全。
修改后的addToFav方法示例:
private fun addToFav(body: MovieDetailData?) { lifecycleScope.launch(Dispatchers.IO) { // 在IO线程执行数据库查询 val isMovieExists = body?.let { appDb.movieDao().getById(it.Title) } != null // 切回主线程更新UI withContext(Dispatchers.Main) { // 这里可以根据是否存在设置不同的背景(你原来的代码两次都设了同一个资源,可能是笔误?) val bgResource = if (isMovieExists) { R.drawable.favorite_unselected_bg // 假设未选中的背景 } else { R.drawable.favorite_bg // 选中的背景 } binding.imgToolbarBtnFav.setBackgroundResource(bgResource) } // 如果不存在,插入数据库 if (!isMovieExists) { body?.let { appDb.movieDao().insert(it) } } } }
如果你的项目还没引入lifecycleScope的依赖,需要在app模块的build.gradle(或build.gradle.kts)里添加:
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2" // 可以用最新版本
另外提醒下,你原来的代码里不管电影是否已经收藏,都设置了同一个R.drawable.favorite_bg,这可能不符合你的业务逻辑,记得根据实际需求调整背景资源哦~
备注:内容来源于stack exchange,提问作者Nisa Efendioglu

