简体   繁体   English

如何在 Jetpack Compose 中处理 Mapbox Map 的活动生命周期事件?

[英]How to handle activity lifecycle events for Mapbox Map in Jetpack Compose?

in the official documentation for Mapbox SDK for android there is a simple example of map using standard UI library for Android.在 Mapbox SDK for android 的官方文档中,有一个简单的地图示例,该示例使用 Android 的标准 UI 库。 Full documentation for completeness of the question can be found here .可以在此处找到有关问题完整性的完整文档。

The code mentioned there is like this:那里提到的代码是这样的:

private var mapView: MapView? = null
 
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
 
Mapbox.getInstance(this, getString(R.string.mapbox_access_token))
 
setContentView(R.layout.activity_main)
 
mapView = findViewById(R.id.mapView)
mapView?.onCreate(savedInstanceState)
mapView?.getMapAsync { mapboxMap ->
 
    mapboxMap.setStyle(Style.MAPBOX_STREETS) {
 
        // Map is set up and the style has loaded. Now you can add data or make other map adjustments
    }
 
   }
}

Code for handling activity and mapbox map lifecycle events is like this:处理活动和mapbox地图生命周期事件的代码是这样的:

override fun onStart() {
    super.onStart()
    mapView?.onStart()
}
 
override fun onResume() {
    super.onResume()
    mapView?.onResume()
}
 
override fun onPause() {
    super.onPause()
    mapView?.onPause()
}
 
override fun onStop() {
    super.onStop()
    mapView?.onStop()
}
 
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    mapView?.onSaveInstanceState(outState)
}
 
override fun onLowMemory() {
    super.onLowMemory()
    mapView?.onLowMemory()
}
 
override fun onDestroy() {
    super.onDestroy()
    mapView?.onDestroy()
}

My question is, if one is using mapbox map in jetpack compose, are those events of the map dealt with automatically, or does developer need to handle them himself?我的问题是,如果在jetpack compose中使用mapbox地图,地图的那些事件是自动处理的,还是开发人员需要自己处理? I am asking, because I do not want to have any doubts how to deal with the best practices regarding the AndroidView in jetpack compose especially when the map is placed in composable outside of any particular activity or fragment.我在问,因为我不想对如何处理关于 jetpack compose 中的 AndroidView 的最佳实践有任何疑问,尤其是当地图被放置在任何特定活动或片段之外的可组合中时。

Jetpack compose code snippet for completeness: Jetpack 为完整性编写代码片段:

@Composable
fun MapWithFab() {

    ConstraintLayout(modifier = Modifier.fillMaxSize()) {
        val mapboxMap = createRef()
        val fab = createRef()

        AndroidView(
            modifier = Modifier
                .fillMaxSize()
                .padding(bottom = 35.dp)
                .constrainAs(mapboxMap) {
                    top.linkTo(parent.top)
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    bottom.linkTo(parent.bottom)
                },
            factory = { context ->
                Mapbox.getInstance(
                    context,
                    context.getString(R.string.mapbox_access_token)
                )
                MapView(context).apply {
                    getMapAsync { mapboxMap ->
                        mapboxMap.setStyle(Style.MAPBOX_STREETS)

                        val position = CameraPosition.Builder()
                            .target(LatLng(51.04004014308637, 13.744085852141072))
                            .zoom(15.0)
                            .build()

                        mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 1)
                    }
                }
            }
        )

        FloatingActionButton(
            onClick = { },
            modifier = Modifier
                .padding(25.dp)
                .width(50.dp)
                .height(50.dp)
                .constrainAs(fab) {
                    end.linkTo(mapboxMap.end)
                    bottom.linkTo(mapboxMap.bottom)
                }
        ) {

        }
    }
}

Thank you for your answers and ideas.感谢您的回答和想法。

It turns out to be mentioned in one of the example projects on compose right from the google, the code and the project on github can be found here事实证明,谷歌的 compose 示例项目之一中提到了这一点,github 上的代码和项目可以在这里找到

It can be done something like this:可以这样做:

@Composable
fun MapWrapper() {
    ConstraintLayout(modifier = Modifier.fillMaxSize()) {
        val mapboxMap = createRef()
        val fab = createRef()
        val mapView = rememberMapViewWithLifecycle()


        AndroidView(
            factory = {mapView},
            modifier = Modifier.constrainAs(mapboxMap) {
                top.linkTo(parent.top)
                bottom.linkTo(parent.bottom)
                start.linkTo(parent.start)
                end.linkTo(parent.end)
        })

        FloatingActionButton(
            onClick = {

            },
            modifier = Modifier
                .padding(25.dp)
                .width(50.dp)
                .height(50.dp)
                .constrainAs(fab) {
                    end.linkTo(mapboxMap.end)
                    bottom.linkTo(mapboxMap.bottom)
                }
        ) {

        }
    }
}

@Composable
fun rememberMapViewWithLifecycle(): MapView {
    val context = LocalContext.current
    val mapView = remember {
        Mapbox.getInstance(
            context,
            context.getString(R.string.mapbox_access_token)
        )
        MapView(context).apply {
            val mapView = this
            getMapAsync { mapboxMap ->
                mapboxMap.setStyle(Style.MAPBOX_STREETS)

                val position = CameraPosition.Builder()
                    .target(LatLng(70.04004014308637, -20.744085852141072))
                    .zoom(15.0)
                    .build()

                mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 1)

                mapboxMap.getStyle {
                }
            }
        }
    }

    val lifecycle = LocalLifecycleOwner.current.lifecycle
    DisposableEffect(lifecycle, mapView) {
        // Make MapView follow the current lifecycle
        val lifecycleObserver = getMapLifecycleObserver(mapView)
        lifecycle.addObserver(lifecycleObserver)
        onDispose {
            lifecycle.removeObserver(lifecycleObserver)
        }
    }

    return mapView
}

/**
 * Handles lifecycle of provided mapView
 */
private fun getMapLifecycleObserver(mapView: MapView): LifecycleEventObserver =
    LifecycleEventObserver { _, event ->
        when (event) {
            Lifecycle.Event.ON_CREATE -> mapView.onCreate(Bundle())
            Lifecycle.Event.ON_START -> mapView.onStart()
            Lifecycle.Event.ON_RESUME -> mapView.onResume()
            Lifecycle.Event.ON_PAUSE -> mapView.onPause()
            Lifecycle.Event.ON_STOP -> mapView.onStop()
            Lifecycle.Event.ON_DESTROY -> mapView.onDestroy()
            else -> throw IllegalStateException()
        }
    }

It can be implemented this way for pretty much any AndroidView, which needs to be responsive for the lifecycle events.几乎任何 AndroidView 都可以通过这种方式实现,它需要对生命周期事件做出响应。 The only thing which this implementation lacks is that there is no handling of onLowMemory() case.这个实现唯一缺乏的是没有处理 onLowMemory() 情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM