Skip to content

Instantly share code, notes, and snippets.

@terrakok
Last active February 12, 2020 13:18
Show Gist options
  • Save terrakok/cd080a6a0213ef7430bdd72ebe92c9ef to your computer and use it in GitHub Desktop.
Save terrakok/cd080a6a0213ef7430bdd72ebe92c9ef to your computer and use it in GitHub Desktop.
import android.os.Bundle
import android.support.annotation.LayoutRes
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.arellomobile.mvp.MvpDelegate
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.OnMapReadyCallback
/**
* @author Konstantin Tskhovrebov (aka terrakok). Date: 01.03.17
*/
abstract class BaseMapFragment : Fragment(), OnMapReadyCallback {
private var isGoogleMapReady = false
private var isStateSaved = false
private val mvpDelegate: MvpDelegate<out BaseMapFragment> by lazy { MvpDelegate(this) }
protected lateinit var mapView: MapView
companion object {
private const val KEY_MAP_VIEW_OUT_STATE = "mapview_state"
}
/**
* Provide layout of the fragment
*/
@get:LayoutRes
protected abstract val fragmentLayout: Int
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mvpDelegate.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(fragmentLayout, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mapView = view.findViewById(R.id.mapView) as MapView
if (savedInstanceState == null) {
mapView.onCreate(null)
} else {
mapView.onCreate(savedInstanceState.getBundle(KEY_MAP_VIEW_OUT_STATE))
}
isGoogleMapReady = false
mapView.getMapAsync(this)
}
override fun onStart() {
super.onStart()
isStateSaved = false
if (isGoogleMapReady) {
mvpDelegate.onAttach()
}
}
override fun onResume() {
super.onResume()
isStateSaved = false
if (isGoogleMapReady) {
mvpDelegate.onAttach()
}
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mvpDelegate.onDetach()
}
override fun onDestroyView() {
super.onDestroyView()
mvpDelegate.onDetach()
mvpDelegate.onDestroyView()
}
override fun onDestroy() {
super.onDestroy()
//We leave the screen and respectively all fragments will be destroyed
if (activity.isFinishing) {
mvpDelegate.onDestroy()
return
}
// When we rotate device isRemoving() return true for fragment placed in backstack
// http://stackoverflow.com/questions/34649126/fragment-back-stack-and-isremoving
if (isStateSaved) {
isStateSaved = false
return
}
if (isRemoving) {
mvpDelegate.onDestroy()
}
mapView.onDestroy()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
isStateSaved = true
mvpDelegate.onSaveInstanceState(outState)
mvpDelegate.onDetach()
val bundle = Bundle()
mapView.onSaveInstanceState(bundle)
outState.putBundle(KEY_MAP_VIEW_OUT_STATE, bundle)
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
override fun onMapReady(googleMap: GoogleMap) {
isGoogleMapReady = true
mvpDelegate.onAttach()
}
}
@rsajob
Copy link

rsajob commented Apr 13, 2019

Данный вариант не корректно работает, когда происходит пересоздание вью без пересоздания фрагмента. Это происходит например при attach/detach (обычно исползуется для навигации по табам)

Суть вот в чём. При detach фрагмент (его инстенс) не унитчтожается, а остаётся висеть в памяти, но его view уничтожается. Вызывается onDestroyView() и при этом onSaveInstanceState() не вызывается и соответственно состояние mapView не сохраняется. Затем при attach у фрагмента уже не вызывается onCreate(), а сразу вызывается onCeateView() и получается так, что вью пересоздана без восстановления состояния.

Решил проблему добавлением специального поля mapBundle и при вызове onDestroyView() сохраняю состояние в него, а в onViewCreated() восстанавливаю если savedInstanceState == null.

Выложил в gist, там 2 варианта, c MapView (MvpMapViewFragment.kt) и c SupportMapFragment (MvpMapFragment). Кстати при использовании SupportMapFragment этой проблеы нет т.к. SupportMapFragment при этом уничтожается вместе со вью и сам заботится о восстановлени совего состояния состояния.

https://gist.github.com/rsajob/fbd6741e9e04d62d7e3185526d651805

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment