mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 14:24:43 -04:00
Resolved ANRs on new game screen when user has a lot of maps, by deferring the parsing of most of the map files until after the screen has loaded
This commit is contained in:
parent
2028c0569b
commit
ac85888cfd
@ -16,6 +16,7 @@ import com.unciv.ui.components.input.onChange
|
|||||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||||
import com.unciv.ui.screens.victoryscreen.LoadMapPreview
|
import com.unciv.ui.screens.victoryscreen.LoadMapPreview
|
||||||
import com.unciv.utils.Concurrency
|
import com.unciv.utils.Concurrency
|
||||||
|
import io.ktor.util.collections.*
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import com.badlogic.gdx.utils.Array as GdxArray
|
import com.badlogic.gdx.utils.Array as GdxArray
|
||||||
@ -34,7 +35,7 @@ class MapFileSelectTable(
|
|||||||
private class MapWrapper(val fileHandle: FileHandle, val mapParameters: MapParameters) {
|
private class MapWrapper(val fileHandle: FileHandle, val mapParameters: MapParameters) {
|
||||||
override fun toString(): String = mapParameters.baseRuleset + " | " + fileHandle.name()
|
override fun toString(): String = mapParameters.baseRuleset + " | " + fileHandle.name()
|
||||||
}
|
}
|
||||||
private val mapWrappers= ArrayList<MapWrapper>()
|
private val mapWrappers = ConcurrentSet<MapWrapper>()
|
||||||
|
|
||||||
private val columnWidth = newGameScreen.getColumnWidth()
|
private val columnWidth = newGameScreen.getColumnWidth()
|
||||||
|
|
||||||
@ -53,6 +54,10 @@ class MapFileSelectTable(
|
|||||||
|
|
||||||
mapFileSelectBox.onChange { onSelectBoxChange() }
|
mapFileSelectBox.onChange { onSelectBoxChange() }
|
||||||
|
|
||||||
|
addMapWrappersSemiAsync()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addMapWrappersSemiAsync(){
|
||||||
val mapFilesSequence = sequence<FileHandle> {
|
val mapFilesSequence = sequence<FileHandle> {
|
||||||
yieldAll(MapSaver.getMaps().asSequence())
|
yieldAll(MapSaver.getMaps().asSequence())
|
||||||
for (modFolder in RulesetCache.values.mapNotNull { it.folderLocation }) {
|
for (modFolder in RulesetCache.values.mapNotNull { it.folderLocation }) {
|
||||||
@ -60,17 +65,25 @@ class MapFileSelectTable(
|
|||||||
if (mapsFolder.exists())
|
if (mapsFolder.exists())
|
||||||
yieldAll(mapsFolder.list().asSequence())
|
yieldAll(mapsFolder.list().asSequence())
|
||||||
}
|
}
|
||||||
}
|
}.sortedByDescending { it.lastModified() }
|
||||||
|
|
||||||
|
// We only really need ONE map to be loaded to tell us "isNotEmpty" and "recentlySavedMapExists"
|
||||||
for (mapFile in mapFilesSequence) {
|
// The rest we can defer, so that users don't get ANRs when opening the new game screen
|
||||||
|
// because the game wants to load ALL the maps before first render
|
||||||
|
fun tryAddMapFile(mapFile: FileHandle){
|
||||||
val mapParameters = try {
|
val mapParameters = try {
|
||||||
MapSaver.loadMapParameters(mapFile)
|
MapSaver.loadMapParameters(mapFile)
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
mapWrappers.add(MapWrapper(mapFile, mapParameters))
|
mapWrappers.add(MapWrapper(mapFile, mapParameters))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (mapFile in mapFilesSequence) {
|
||||||
|
if (mapWrappers.isEmpty()) tryAddMapFile(mapFile)
|
||||||
|
// Each other map is loaded in another thread, so we can multiplex the IO and CPU capabilities
|
||||||
|
else Concurrency.run { tryAddMapFile(mapFile) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user