如何在 Jetpack Compose 中处理 Mapbox Map 的 activity 生命周期事件?
How to handle activity lifecycle events for Mapbox Map in Jetpack Compose?
在 android 的 Mapbox SDK 官方文档中,有一个使用标准 UI 库 Android 的简单地图示例。可以找到有关问题完整性的完整文档 here。
那里提到的代码是这样的:
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
}
}
}
处理activity和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()
}
我的问题是,如果在 jetpack compose 中使用 mapbox 地图,地图的那些事件是自动处理的,还是需要开发人员自己处理?
我在问,因为我不想对如何处理关于 Jetpack 中的 AndroidView 的最佳实践有任何疑问,特别是当地图放置在任何特定 activity 或片段之外的可组合时.
Jetpack compose 代码片段的完整性:
@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)
}
) {
}
}
}
感谢您的回答和想法。
原来在 google 上的 compose 示例项目之一中提到了,github 上的代码和项目可以找到 here
可以这样做:
@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()
}
}
几乎所有需要响应生命周期事件的 AndroidView 都可以通过这种方式实现。这个实现唯一缺少的是没有处理 onLowMemory() 案例。
更新 - 注意:上面的解决方案是解决 MapboxMaps v9 的生命周期,MapboxMaps v10 已经集成了它。
在 android 的 Mapbox SDK 官方文档中,有一个使用标准 UI 库 Android 的简单地图示例。可以找到有关问题完整性的完整文档 here。
那里提到的代码是这样的:
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
}
}
}
处理activity和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()
}
我的问题是,如果在 jetpack compose 中使用 mapbox 地图,地图的那些事件是自动处理的,还是需要开发人员自己处理? 我在问,因为我不想对如何处理关于 Jetpack 中的 AndroidView 的最佳实践有任何疑问,特别是当地图放置在任何特定 activity 或片段之外的可组合时.
Jetpack compose 代码片段的完整性:
@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)
}
) {
}
}
}
感谢您的回答和想法。
原来在 google 上的 compose 示例项目之一中提到了,github 上的代码和项目可以找到 here
可以这样做:
@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()
}
}
几乎所有需要响应生命周期事件的 AndroidView 都可以通过这种方式实现。这个实现唯一缺少的是没有处理 onLowMemory() 案例。
更新 - 注意:上面的解决方案是解决 MapboxMaps v9 的生命周期,MapboxMaps v10 已经集成了它。