Fragment中使用高德MapView,切换页面时遇到问题解决过程

问题描述

最近的一个项目中,首页使用了ViewPager+Fragment模式,在ViewPager里有一个Flutter页面和一个用MapView写的地图页面。从地图切换过去的时候MapView会有一个拉伸的截图覆盖在Flutter页面上了。但是Flutter页面实际上是加载出来的,并且如点击事件等都可以正常响应,很是奇怪。

问题分析

因为点击事件都能被响应,说明Flutter页面已经加载完成了,只是被遮挡了,故把Flutter页面从怀疑对象中排除。所以把注意力转移到地图页面。地图页面里嵌入里一个高德SDK提供的MapView,应该是这里在切换时出问题了。

第一次尝试

尝试在地图页面切换时将MapView隐藏起来,这样就不会产生截图了。由于是ViewPager+Fragment的组合,所以在setUserVisibleHint()中进行操作,代码如下:

override fun setUserVisibleHint(isVisibleToUser: Boolean) {
    super.setUserVisibleHint(isVisibleToUser)
    if (isVisibleToUser)  mapView?.visibility = View.VISIBLE  else   mapView?.visibility = View.GONE
}

到这里确实解决了切换存在截图问题,但是同时引入了两个新问题。

问题1 切换时出现闪屏黑屏

从地图切换其他页面时会出现一次短暂的黑屏
这个问题应该是高德地图的问题,因为MapView中封装了一个GlSurfaceView,SurfaceView和其他View不同,他有自己良好的缓冲以及数据存取机制,系统对他有特殊处理。在网上也有很多关于SurfaceView黑屏的解决办法,如

在activity的oncreate方法中加入getWindow().setFormat(PixelFormat.TRANSLUCENT);

经过测试对我的项目无效,在翻看了高德API手册里发现了一个叫做TextureMapView的东东,对他的介绍是这样的:

一个显示地图的视图(View),它负责从服务端获取地图数据,它将会捕捉屏幕触控手势事件。 使用这个类必须按照它的生命周期进行操控,你必须参照以下方法onCreate(Bundle)、 onResume()、onPause()、onDestroy()。等声明周期函数。
它和MapView的区别在于,TextureMapView是一个TextureView而MapView是一个GLSurfaceView。
所以TextureMapView 可以和其他的GlSurfaceView(比如相机)共存不会出现穿透现象,也可以放在ViewPager中不会出现滑动黑边现象。

这个完美应对我现在的需求啊,于是乎将MapView替换为TextureMapView,果然解决了闪屏问题。

问题2 MapView中添加过多Marker和绘制的点线后,在切换时闪屏黑屏时间明显变长。

黑屏问题解决后,性能问题也是不能不解决的。在Activity中使用MapView的时候,切换到其他页面时MapView会调用onPasue()方法,再回到当前页面时会调用onRsume()方法,虽然不知道onPasue()方法具体做了什么,但是我们知道地图时很消耗内存的控件,所以不难猜测在onPasue()方法中肯定做了相关资源的释放和一些性能上的优化操作。
根据这个思路,在fragment不可见时主动调用一次onPause(),在可见时再调用onResume()。

最终解决办法

修改后的代码如下:

override fun setUserVisibleHint(isVisibleToUser: Boolean) {
    super.setUserVisibleHint(isVisibleToUser)
    if (isVisibleToUser) {      
        mapView?.onResume()
        mapView?.visibility = View.VISIBLE
    } else {
        mapView?.onPause()      
        mapView?.visibility = View.GONE
    }
}

代码很简单,再次运行后顺利的解决了问题。

你可能感兴趣的:(Fragment中使用高德MapView,切换页面时遇到问题解决过程)