使用NavController返回后MapView加载崩溃问题排查
MapView返回导航后加载报错:Map size can't be 0 问题解析与修复
错误原因
这个错误的核心是调用newLatLngBounds(LatLngBounds, int)时,MapView还未完成布局测量,当前尺寸为0:
- 通过NavController的
navigateUp()返回页面时,Fragment的View会重新创建,但MapView的onLayout方法尚未执行完成,此时你在onMapReady中调用了依赖地图尺寸的方法(比如你的mapFocus(false)),就会触发该异常。 - SupportMapFragment内部封装了等待布局完成的逻辑,会自动延迟到View尺寸确定后再执行相关地图操作,因此不会出现这个问题。
你的生命周期实现问题
当前MapView的生命周期管理存在两处问题:
- 方法调用顺序错误:
onResume中应先调用super.onResume(),再执行mapView.onResume(); - 缺失关键生命周期方法:未覆盖
onPause和onSaveInstanceState,会导致MapView状态丢失或资源泄漏。
修正后的完整生命周期代码
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) mapView = binding.root.findViewById(R.id.gm_resource) mapView.onCreate(savedInstanceState) mapView.getMapAsync(this) } override fun onResume() { super.onResume() // 先执行父类生命周期方法 mapView.onResume() } override fun onPause() { mapView.onPause() super.onPause() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) mapView.onSaveInstanceState(outState) // 保存MapView状态 } override fun onDestroy() { mapView.onDestroy() super.onDestroy() } override fun onLowMemory() { mapView.onLowMemory() super.onLowMemory() }
解决地图视野设置的问题
针对newLatLngBounds的调用,有两种可靠修复方式:
方式1:等待MapView布局完成后再设置视野
在onMapReady中,通过ViewTreeObserver监听MapView的布局完成事件,延迟执行视野设置:
override fun onMapReady(p0: GoogleMap) { map = p0 // 先完成基础配置 map.uiSettings.isMyLocationButtonEnabled = false map.mapType = GoogleMap.MAP_TYPE_SATELLITE map.setOnMapClickListener { requireContext().hideKeyboard(binding.root) } createClusterManager(map) loadResources() moveToolbar() // 等待MapView布局完成后再设置视野 mapView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { // 移除监听,避免重复触发 mapView.viewTreeObserver.removeOnGlobalLayoutListener(this) mapFocus(false) // 此时调用不会报错 } }) }
方式2:使用四参数版本的newLatLngBounds
手动指定地图的宽高尺寸(可根据屏幕尺寸或布局参数估算):
// 假设你需要设置的边界为latLngBounds val width = resources.displayMetrics.widthPixels val height = resources.displayMetrics.heightPixels val padding = 100 // 自定义边距,按需调整 map.moveCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, width, height, padding))
或先用newLatLngZoom设置初始视野,等布局完成后再调整:
// 先设置默认缩放级别 map.moveCamera(CameraUpdateFactory.newLatLngZoom(centerLatLng, 12f)) // 后续按方式1等待布局完成后调用双参数版本的newLatLngBounds
内容的提问来源于stack exchange,提问作者Danwolve
相关产品推荐
相关产品推荐

