Skip to content

Instantly share code, notes, and snippets.

@rsajob
Last active April 13, 2019 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rsajob/fbd6741e9e04d62d7e3185526d651805 to your computer and use it in GitHub Desktop.
Save rsajob/fbd6741e9e04d62d7e3185526d651805 to your computer and use it in GitHub Desktop.
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import com.arellomobile.mvp.MvpDelegate
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.MapView
/**
* Для использования MapView
*
* Created by Roman Savelev (aka @rsa) on 09.04.2019
*/
abstract class MvpMapViewFragment : Fragment() {
abstract val mapResId:Int
open fun onMapReady() {}
private var isMapReady = false
private var mIsStateSaved = false
lateinit var map: GoogleMap
lateinit var mapView: MapView
private val mvpDelegate: MvpDelegate<out MvpMapViewFragment> by lazy { MvpDelegate(this) }
var mapBundle:Bundle? = null
companion object {
private const val KEY_MAP_VIEW_STATE = "mapview_state"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mvpDelegate.onCreate(savedInstanceState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mapView = view.findViewById(mapResId) as MapView
if (savedInstanceState == null) {
mapView.onCreate(mapBundle)
}else
mapView.onCreate(savedInstanceState.getBundle(KEY_MAP_VIEW_STATE))
isMapReady = false
mapView.getMapAsync {
map = it
isMapReady = true
onMapReady()
mvpDelegate.onAttach()
}
}
override fun onStart() {
super.onStart()
mIsStateSaved = false
if (isMapReady) {
mvpDelegate.onAttach()
}
}
override fun onResume() {
super.onResume()
mIsStateSaved = false
if (isMapReady) {
mvpDelegate.onAttach()
}
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mvpDelegate.onDetach()
mapView.onStop()
}
override fun onDestroyView() {
super.onDestroyView()
mvpDelegate.onDetach()
mvpDelegate.onDestroyView()
// Нужно сохранить состояние тут, потому что при detatch/attach фрагмента
// (например если используется bottom navigation) вызов onSaveInstanceState()/onCreate()
// не происходят, а просто пересоздаётся view onViewCreate()/onDestroyView(),
// при этом инстенс фрагмента не уничтожается и переменная mapBundle хранит нужное состояние
mapBundle = Bundle().also { mapView.onSaveInstanceState(it) }
if (isMapReady)
map.clear() // For avoid the memory leak
}
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) {
mIsStateSaved = false
return
}
// See https://github.com/Arello-Mobile/Moxy/issues/24
var anyParentIsRemoving = false
var parent = parentFragment
while (!anyParentIsRemoving && parent != null) {
anyParentIsRemoving = parent.isRemoving
parent = parent.parentFragment
}
if (isRemoving || anyParentIsRemoving) {
mvpDelegate.onDestroy()
}
mapView.onDestroy()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mIsStateSaved = true
mvpDelegate.onSaveInstanceState(outState)
mvpDelegate.onDetach()
mapBundle = Bundle()
mapView.onSaveInstanceState(mapBundle)
outState.putBundle(KEY_MAP_VIEW_STATE, mapBundle)
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
}
<FrameLayout 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"
>
<com.google.android.gms.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import com.arellomobile.mvp.MvpDelegate
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.SupportMapFragment
/**
* Для использования SupportMapFragment
*
* Created by Roman Savelev (aka @rsa) on 09.04.2019
*/
abstract class MvpMapFragment : Fragment() {
abstract val mapContainerId:Int
open fun onMapReady() { }
private var isMapReady = false
private var mIsStateSaved: Boolean = false
lateinit var map: GoogleMap
val mapView: View get() = (childFragmentManager.findFragmentById(mapContainerId) as SupportMapFragment).view!!
private val mvpDelegate: MvpDelegate<out MvpMapFragment> by lazy { MvpDelegate(this) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
var mapFragment = childFragmentManager.findFragmentById(mapContainerId) as? SupportMapFragment
if (mapFragment == null) {
mapFragment = SupportMapFragment()
childFragmentManager.beginTransaction().replace(mapContainerId, mapFragment).commit()
}
isMapReady = false
mapFragment.getMapAsync {
this.map = it
isMapReady = true
onMapReady()
mvpDelegate.onAttach()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mvpDelegate.onCreate(savedInstanceState)
}
override fun onStart() {
super.onStart()
mIsStateSaved = false
if (isMapReady)
mvpDelegate.onAttach()
}
override fun onResume() {
super.onResume()
mIsStateSaved = false
if (isMapReady)
mvpDelegate.onAttach()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mIsStateSaved = true
mvpDelegate.onSaveInstanceState(outState)
mvpDelegate.onDetach()
}
override fun onStop() {
super.onStop()
mvpDelegate.onDetach()
}
override fun onDestroyView() {
super.onDestroyView()
mvpDelegate.onDetach()
mvpDelegate.onDestroyView()
if (isMapReady)
map.clear() // For avoid the memory leak
}
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 (mIsStateSaved) {
mIsStateSaved = false
return
}
// See https://github.com/Arello-Mobile/Moxy/issues/24
var anyParentIsRemoving = false
var parent = parentFragment
while (!anyParentIsRemoving && parent != null) {
anyParentIsRemoving = parent.isRemoving
parent = parent.parentFragment
}
if (isRemoving || anyParentIsRemoving) {
mvpDelegate.onDestroy()
}
}
}
<FrameLayout 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"
>
<FrameLayout
android:id="@+id/map_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment