I have Bottom Navigation View
with 4 tab and one of them contains Huawei MapView
. When I switch from Tab A which contains MapView to Tab B, Leak Canary
show a memory leak which related to MapView
Fragment
only contains MapView
, there is not any extra view
class MapFragment : BaseFragment(R.layout.fragment_map), OnMapReadyCallback {
private var hMap: HuaweiMap? = null
companion object {
private const val MAPVIEW_BUNDLE_KEY = "MapViewBundleKey"
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initHuaweiMap(savedInstanceState)
}
private fun initHuaweiMap(savedInstanceState: Bundle?) {
var mapViewBundle: Bundle? = null
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY)
}
map_view?.apply {
onCreate(mapViewBundle)
getMapAsync(this@MapFragment)
}
}
override fun onMapReady(map: HuaweiMap?) {
hMap = map
hMap?.setMapStyle(MapStyleOptions.loadRawResourceStyle(requireContext(), R.raw.mapstyle_night_hms))
hMap?.isMyLocationEnabled = false // Enable the my-location overlay.
hMap?.uiSettings?.isMyLocationButtonEnabled = false // Enable the my-location icon.
hMap?.uiSettings?.isZoomControlsEnabled = false // Disable zoom-in zoom-out buttons
}
override fun onStart() {
map_view?.onStart()
super.onStart()
}
override fun onStop() {
map_view?.onStop()
super.onStop()
}
override fun onDestroy() {
map_view?.onDestroy()
super.onDestroy()
}
override fun onPause() {
map_view?.onPause()
super.onPause()
}
override fun onResume() {
map_view?.onResume()
super.onResume()
}
override fun onLowMemory() {
map_view?.onLowMemory()
super.onLowMemory()
}
override fun onDestroyView() {
hMap?.clear()
hMap = null
map_view?.onDestroy()
super.onDestroyView()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
var mapViewBundle = outState.getBundle(MAPVIEW_BUNDLE_KEY)
if (mapViewBundle == null) {
mapViewBundle = Bundle()
outState.putBundle(MAPVIEW_BUNDLE_KEY, mapViewBundle)
}
map_view?.onSaveInstanceState(mapViewBundle)
}
}
My Layout file
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.tabs.profile.Mapragment">
<com.huawei.hms.maps.MapView
android:id="@+id/map_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:cameraZoom="14"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I put all lifecycle method related to MapView but still cause a memory leak
Last step it says;
MapFragment received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks)
I clear the references at onDestroyView
but still get same error. How can I prevent this memory leak?
You are advised to use MapFragment (extends the native Fragment component of Android and can be used to add a map to an app in the simplest way), or SupportMapFragment, instead of using your Fragment to embed Huawei MapView.
Update: Please check the following codes:
activity_main.xml
fragment_map.xml