Context
Prerequisites
1. Have a slow-slow connection: e.g.: on emulator go to Developers options, Network Download Rate Limit, set 128kb.
2. Enable screen rotation.
Actions
Result
It seems like basemap's baseLayers remote loading is not cancelled when MapView is destroyed due to lifecycle. cancelLoad on any item (ArcGISMap, Basemap, Layer) doesn't give any effect.
Code snippet I was playing with to try to understand the issue:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// authentication with an API key or named user is
// required to access basemaps and other location services
ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY)
enableEdgeToEdge()
setContent {
SampleAppTheme {
val context = LocalContext.current
// create a map with a navigation night basemap style
val map = remember { ArcGISMap(Basemap()) }
var insets by remember { mutableStateOf(PaddingValues(0.dp)) }
MapView(
modifier = Modifier.fillMaxSize(),
arcGISMap = map,
isAttributionBarVisible = false,
insets = insets
)
Column(
modifier = Modifier
.fillMaxSize()
.padding(WindowInsets.systemBars.asPaddingValues()),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
var count by remember {
mutableIntStateOf(0)
}
Button(
onClick = { count++ },
content = { Text(text = "Click me") }
)
Text(text = count.toString())
}
LaunchedEffect(Unit) {
delay(500L)
insets = PaddingValues(32.dp)
}
LaunchedEffect(Unit) {
delay(100L)
map.basemap.value?.baseLayers?.add(ArcGISTiledLayer("https://ibasemaps-api.arcgis.com/arcgis/rest/services/World_Imagery/MapServer"))
delay(500L)
map.basemap.value?.referenceLayers?.add(ArcGISVectorTiledLayer("https://basemapstyles-api.arcgis.com/arcgis/rest/services/styles/v2/layers/arcgis/imagery/labels"))
}
DisposableEffect(Unit) {
onDispose {
map.basemap
println("!")
}
}
}
}
}
}
Also, what I've found in the other project is that ArcGISMap seems to be leaking inside NetworkAuthenticationInterceptor:
in previous release 200.3 display-map sample has another issue on rotation with bad connection: I could see two MapView in the heap, which makes me think the problem could be connected with 200.4 leak 🤔 could it be rendering thread / Looper and the lifecycle in the GeoView?
Also, it feels like reading tiles is done via DefaultDispatcher. As a result -> with bad connection default dispatcher is over-queued easily as it's not intended for long-running operations. If so, http tile reading operations should be switched to IO and asap.
The hacky solution is:
private fun ArcGISEnvironment.fixCoroutineScope() = this::class.apply {
val setCoroutineScopeFun = this.java.methods.find { it.name.startsWith("setScope") } ?: return@apply
val arcgisCoroutineScope =
CoroutineScope(
SupervisorJob() + Dispatchers.IO +
CoroutineExceptionHandler { _, throwable ->
Log.w("ArcGISEnvironment", throwable)
},
)
setCoroutineScopeFun.invoke(this.objectInstance, arcgisCoroutineScope)
}
Would be cool to see setScope fun being open -> to control the dispatcher, but also e.g. if we want to react on exceptions on our (client) terms.