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

切换Fragment时如何阻止Google Map重新加载?

解决DrawerLayout切换时Google Map重复初始化的问题

你的问题核心在于每次切换导航项时都新建了MapFragment实例,导致每次切回地图页都会重新加载SupportMapFragment,进而触发地图初始化。下面给你两种可行的解决方案,先从最直接的复用Fragment实例开始:

方案一:复用Fragment实例(推荐)

我们在宿主Activity中缓存各个Fragment的实例,切换时直接复用而非新建,同时让MapFragment保留自身状态,避免重建。

第一步:修正宿主Activity的导航逻辑

把导航监听移到Activity中(你的原代码里把导航监听写在MapFragment里是不合理的),并添加Fragment缓存:

class MainActivity : AppCompatActivity() {
    private lateinit var drawerLayout: DrawerLayout
    // 用Map缓存已创建的Fragment实例
    private val fragmentCache = mutableMapOf<Int, Fragment>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        drawerLayout = findViewById(R.id.drawer_layout)
        val navigationView: NavigationView = findViewById(R.id.nav_view)

        // 初始化默认显示的地图Fragment
        if (savedInstanceState == null) {
            val mapFragment = MapFragment()
            fragmentCache[R.id.nav_map] = mapFragment
            supportFragmentManager.beginTransaction()
                .replace(R.id.main_activity_frame, mapFragment)
                .commit()
            navigationView.setCheckedItem(R.id.nav_map)
        }

        navigationView.setNavigationItemSelectedListener { menuItem ->
            when (menuItem.itemId) {
                R.id.nav_logout -> {
                    val intent = Intent(this, LoginActivity::class.java)
                    startActivity(intent)
                    true
                }
                else -> {
                    // 从缓存取Fragment,不存在才新建
                    val targetFragment = fragmentCache.getOrPut(menuItem.itemId) {
                        when (menuItem.itemId) {
                            R.id.nav_map -> MapFragment()
                            R.id.nav_forecast -> ForecastFragment()
                            R.id.nav_app_info -> AboutFragment()
                            else -> MapFragment()
                        }
                    }
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_activity_frame, targetFragment)
                        .commit()
                    menuItem.isChecked = true
                    drawerLayout.closeDrawers()
                    true
                }
            }
        }
    }
}

第二步:修改MapFragment保留状态

让MapFragment保留自身实例,并复用内部的SupportMapFragment:

class MapFragment : Fragment(), OnMapReadyCallback {
    private var mMap: GoogleMap? = null
    private var mapFragment: SupportMapFragment? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 开启实例保留,防止Fragment被销毁重建
        retainInstance = true
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_map, container, false)
        // 优先从子Fragment管理器找已存在的SupportMapFragment
        mapFragment = childFragmentManager.findFragmentById(R.id.map_new) as? SupportMapFragment
        if (mapFragment == null) {
            // 仅当不存在时才新建并添加
            mapFragment = SupportMapFragment.newInstance()
            childFragmentManager.beginTransaction()
                .replace(R.id.map_new, mapFragment!!)
                .commit()
        }
        mapFragment?.getMapAsync(this)
        return view
    }

    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap
        // 恢复之前保存的地图状态(比如相机位置)
        savedInstanceState?.getParcelable<CameraPosition>("camera_position")?.let {
            mMap?.moveCamera(CameraUpdateFactory.newCameraPosition(it))
        }
        // 你的其他地图初始化逻辑写在这里
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        // 保存当前地图的相机位置,下次恢复
        mMap?.cameraPosition?.let {
            outState.putParcelable("camera_position", it)
        }
    }
}

关于WeakReference的思路补充

你提到的WeakReference关联MapView,其实是用来避免内存泄漏的场景(比如在非生命周期持有MapView引用),但在这个问题里,复用Fragment实例的方案已经足够解决重复初始化的问题,不需要额外用WeakReference。如果一定要尝试,核心是在MapFragment中用WeakReference持有MapView,确保Fragment销毁时能正确释放,但这不是解决当前问题的最优解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:57:25