問題描述
最近的一個(gè)項(xiàng)目中,首頁使用了ViewPager+Fragment模式能扒,在ViewPager里有一個(gè)Flutter頁面和一個(gè)用MapView寫的地圖頁面块茁。從地圖切換過去的時(shí)候MapView會有一個(gè)拉伸的截圖覆蓋在Flutter頁面上了齿坷。但是Flutter頁面實(shí)際上是加載出來的,并且如點(diǎn)擊事件等都可以正常響應(yīng)数焊,很是奇怪永淌。
問題分析
因?yàn)辄c(diǎn)擊事件都能被響應(yīng),說明Flutter頁面已經(jīng)加載完成了佩耳,只是被遮擋了遂蛀,故把Flutter頁面從懷疑對象中排除。所以把注意力轉(zhuǎn)移到地圖頁面干厚。地圖頁面里嵌入里一個(gè)高德SDK提供的MapView李滴,應(yīng)該是這里在切換時(shí)出問題了。
第一次嘗試
嘗試在地圖頁面切換時(shí)將MapView隱藏起來蛮瞄,這樣就不會產(chǎn)生截圖了所坯。由于是ViewPager+Fragment的組合,所以在setUserVisibleHint()
中進(jìn)行操作挂捅,代碼如下:
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (isVisibleToUser) mapView?.visibility = View.VISIBLE else mapView?.visibility = View.GONE
}
到這里確實(shí)解決了切換存在截圖問題芹助,但是同時(shí)引入了兩個(gè)新問題。
問題1 切換時(shí)出現(xiàn)閃屏黑屏
從地圖切換其他頁面時(shí)會出現(xiàn)一次短暫的黑屏
這個(gè)問題應(yīng)該是高德地圖的問題闲先,因?yàn)镸apView中封裝了一個(gè)GlSurfaceView
,SurfaceView和其他View不同周瞎,他有自己良好的緩沖以及數(shù)據(jù)存取機(jī)制,系統(tǒng)對他有特殊處理饵蒂。在網(wǎng)上也有很多關(guān)于SurfaceView黑屏的解決辦法声诸,如
在activity的oncreate方法中加入getWindow().setFormat(PixelFormat.TRANSLUCENT);
經(jīng)過測試對我的項(xiàng)目無效,在翻看了高德API手冊里發(fā)現(xiàn)了一個(gè)叫做TextureMapView的東東退盯,對他的介紹是這樣的:
一個(gè)顯示地圖的視圖(View)彼乌,它負(fù)責(zé)從服務(wù)端獲取地圖數(shù)據(jù),它將會捕捉屏幕觸控手勢事件渊迁。 使用這個(gè)類必須按照它的生命周期進(jìn)行操控慰照,你必須參照以下方法onCreate(Bundle)、 onResume()琉朽、onPause()毒租、onDestroy()。等聲明周期函數(shù)箱叁。
它和MapView的區(qū)別在于墅垮,TextureMapView是一個(gè)TextureView而MapView是一個(gè)GLSurfaceView惕医。
所以TextureMapView 可以和其他的GlSurfaceView(比如相機(jī))共存不會出現(xiàn)穿透現(xiàn)象,也可以放在ViewPager中不會出現(xiàn)滑動(dòng)黑邊現(xiàn)象算色。
這個(gè)完美應(yīng)對我現(xiàn)在的需求啊抬伺,于是乎將MapView替換為TextureMapView,果然解決了閃屏問題灾梦。
問題2 MapView中添加過多Marker和繪制的點(diǎn)線后峡钓,在切換時(shí)閃屏黑屏?xí)r間明顯變長。
黑屏問題解決后若河,性能問題也是不能不解決的能岩。在Activity中使用MapView的時(shí)候,切換到其他頁面時(shí)MapView會調(diào)用onPasue()方法萧福,再回到當(dāng)前頁面時(shí)會調(diào)用onRsume()方法捧灰,雖然不知道onPasue()方法具體做了什么,但是我們知道地圖時(shí)很消耗內(nèi)存的控件统锤,所以不難猜測在onPasue()方法中肯定做了相關(guān)資源的釋放和一些性能上的優(yōu)化操作毛俏。
根據(jù)這個(gè)思路,在fragment不可見時(shí)主動(dòng)調(diào)用一次onPause()饲窿,在可見時(shí)再調(diào)用onResume()煌寇。
最終解決辦法
修改后的代碼如下:
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (isVisibleToUser) {
mapView?.onResume()
mapView?.visibility = View.VISIBLE
} else {
mapView?.onPause()
mapView?.visibility = View.GONE
}
}
代碼很簡單逾雄,再次運(yùn)行后順利的解決了問題阀溶。