Reputation: 1487
I have a composable containing a google maps view. When I click on a pin on the map I would like to trigger navController.navigate
so I can navigate to another composable. However, when I call it the application gets stuck instead of navigating. Navigating on a button clicks works as expected.
I have also created a very simple application that is demonstrating the problem. The MainActivity
looks like this:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "Screen1") {
composable("Screen1") {
Button({ navController.navigate("MapsScreen") }) {
Text(text = "Go to Maps")
}
}
composable("MapsScreen") {
val mapView = rememberMapViewWithLifecycle()
AndroidView({ mapView }) { mapView ->
mapView.getMapAsync { map ->
map.setOnInfoWindowClickListener {
navController.navigate("Screen1")
}
val markerOptions = MarkerOptions()
.position(LatLng(41.390205, 2.154007))
.title("Barcelona")
map.addMarker(markerOptions)!!
}
}
}
}
}
}
}
@Composable
fun rememberMapViewWithLifecycle(): MapView {
val context = LocalContext.current
val mapView = remember {
MapView(context).apply {
id = R.id.map
}
}
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
}
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()
}
}
In the project I use androidx.navigation:navigation-compose:2.4.0-beta02
which is the latest version at the moment according to the documentation.
The complete project is available on Github
As an inspiration for the example I have used: Using Google Maps in a Jetpack Compose app and Crane Sample
What could be the problem and how to solve it?
Upvotes: 3
Views: 1288
Reputation: 888
It seems like when you navigate inside the setOnInfoWindowClickListener
method, you'll cause an deadlock.
Try to asynchronously navigate to your target to circumvent the deadlock, e.g. by using GlobalScope.launch
on Dispatchers.Main
, so the listener can run to the end without any deadlock:
map.setOnInfoWindowClickListener {
GlobalScope.launch(Dispatchers.Main) {
navController.navigate("Screen1")
}
}
Upvotes: 3
Reputation: 1487
After some debugging, I come to the conclusion that the problem is somehow related to Lifecycle.Event.ON_STOP -> mapView.onStop()
getMapLifecycleObserver
Removing it solves the problem.
I'm not happy with the solution and would be happy if someone is able to provide a better solution, or at least an answer explaining more details about the problem.
Upvotes: 1