You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

My MapsActivity无错误提示崩溃,协程调用Room数据触发主线程异常

问题原因
  • 直接触发崩溃的原因:你通过by viewModels()懒加载声明ViewModel,首次访问mapsViewModel是在getRoutePoints()方法内部的Dispatchers.IO协程中,属于子线程。而ViewModel初始化过程中需要调用addObserver绑定生命周期,该方法强制要求在主线程执行,因此抛出IllegalStateException异常。
  • 代码还存在隐性逻辑错误:getRoutePoints()方法内部启动异步协程给points赋值后直接返回,此时IO协程还未执行完成,你永远无法拿到数据库返回的真实点位数据,只会得到空列表。
修复方案
  1. 改造getRoutePoints()方法:移除内部自建的协程,将方法改为挂起函数直接返回ViewModel的查询结果。Room的挂起函数默认会自动调度到IO线程执行,不需要手动切换线程。
// Gets the points from room repository through ViewModel
private suspend fun getRoutePoints(): List<PointOfInterest> {
    val route = getRouteId()
    return mapsViewModel.getRoutePoints(route)
}
  1. 替换协程作用域:把onMapReady里自定义的CoroutineScope替换为Android官方提供的lifecycleScope,它会和Activity生命周期绑定,页面销毁时自动取消协程避免内存泄漏,且默认运行在主线程。
override fun onMapReady(googleMap: GoogleMap) {
    mMap = googleMap
    lifecycleScope.launch {
        val listOfPoints = getRoutePoints()
        for (point in listOfPoints) {
            mMap.addMarker(MarkerOptions().position(LatLng( point.latitude, point.longitude)))
            // 替换listOfPoints[0]避免空列表下标越界
            if (point == listOfPoints.firstOrNull()) {
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(point.latitude, point.longitude), 18f))
            }
        }
    }
}

补充:如果项目未引入lifecycle相关ktx依赖,需要在模块级build.gradle中添加依赖:

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2"
  1. 可选优化:如果担心ViewModel懒加载触发时机问题,可以在onCreate方法中提前访问一次mapsViewModel,确保在主线程完成初始化。

内容的提问来源于stack exchange,提问作者albertbuigues

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 21:27:03