Last active
February 12, 2020 13:18
-
-
Save terrakok/cd080a6a0213ef7430bdd72ebe92c9ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Данный вариант не корректно работает, когда происходит пересоздание вью без пересоздания фрагмента. Это происходит например при 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