Fix screens not correctly being dispose()d (#6876)

This commit is contained in:
Timo T 2022-05-21 23:52:02 +02:00 committed by GitHub
parent 81379078fa
commit 91ffa2e185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 52 additions and 42 deletions

View File

@ -67,6 +67,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
val alertBattle = false val alertBattle = false
lateinit var worldScreen: WorldScreen lateinit var worldScreen: WorldScreen
private set
fun getWorldScreenOrNull() = if (this::worldScreen.isInitialized) worldScreen else null fun getWorldScreenOrNull() = if (this::worldScreen.isInitialized) worldScreen else null
var isInitialized = false var isInitialized = false
@ -155,18 +156,30 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
if (gameInfo.civilizations.count { it.playerType == PlayerType.Human } > 1 && !gameInfo.gameParameters.isOnlineMultiplayer) if (gameInfo.civilizations.count { it.playerType == PlayerType.Human } > 1 && !gameInfo.gameParameters.isOnlineMultiplayer)
setScreen(PlayerReadyScreen(gameInfo, gameInfo.getPlayerToViewAs())) setScreen(PlayerReadyScreen(gameInfo, gameInfo.getPlayerToViewAs()))
else { else {
worldScreen = WorldScreen(gameInfo, gameInfo.getPlayerToViewAs()) resetToWorldScreen(WorldScreen(gameInfo, gameInfo.getPlayerToViewAs()))
setWorldScreen()
} }
} }
fun setScreen(screen: BaseScreen) { fun setScreen(screen: BaseScreen) {
val oldScreen = getScreen()
Gdx.input.inputProcessor = screen.stage Gdx.input.inputProcessor = screen.stage
super.setScreen(screen) super.setScreen(screen)
if (oldScreen != getWorldScreenOrNull()) oldScreen.dispose()
} }
fun setWorldScreen() { /**
if (screen != null && screen != worldScreen) screen.dispose() * If called with null [newWorldScreen], disposes of the current screen and sets it to the current stored world screen.
* If the current screen is already the world screen, the only thing that happens is that the world screen updates.
*/
fun resetToWorldScreen(newWorldScreen: WorldScreen? = null) {
if (newWorldScreen != null) {
val oldWorldScreen = getWorldScreenOrNull()
worldScreen = newWorldScreen
// setScreen disposes the current screen, but the old world screen is not the current screen, so need to dispose here
if (screen != oldWorldScreen) {
oldWorldScreen?.dispose()
}
}
setScreen(worldScreen) setScreen(worldScreen)
worldScreen.shouldUpdate = true // This can set the screen to the policy picker or tech picker screen, so the input processor must come before worldScreen.shouldUpdate = true // This can set the screen to the policy picker or tech picker screen, so the input processor must come before
Gdx.graphics.requestRendering() Gdx.graphics.requestRendering()

View File

@ -918,13 +918,13 @@ class AssignedQuest(val questName: String = "",
when (questName) { when (questName) {
QuestName.ClearBarbarianCamp.value -> { QuestName.ClearBarbarianCamp.value -> {
game.setWorldScreen() game.resetToWorldScreen()
game.worldScreen.mapHolder.setCenterPosition(Vector2(data1.toFloat(), data2.toFloat()), selectUnit = false) game.worldScreen.mapHolder.setCenterPosition(Vector2(data1.toFloat(), data2.toFloat()), selectUnit = false)
} }
QuestName.Route.value -> { QuestName.Route.value -> {
game.setWorldScreen() game.resetToWorldScreen()
game.worldScreen.mapHolder.setCenterPosition(gameInfo.getCivilization(assigner).getCapital().location, selectUnit = false) game.worldScreen.mapHolder.setCenterPosition(gameInfo.getCivilization(assigner).getCapital().location, selectUnit = false)
} }
} }
} }
} }

View File

@ -111,7 +111,7 @@ class CityScreen(
private val nextTileToOwn = city.expansion.chooseNewTileToOwn() private val nextTileToOwn = city.expansion.chooseNewTileToOwn()
init { init {
onBackButtonClicked { game.setWorldScreen() } onBackButtonClicked { game.resetToWorldScreen() }
UncivGame.Current.settings.addCompletedTutorialTask("Enter city screen") UncivGame.Current.settings.addCompletedTutorialTask("Enter city screen")
addTiles() addTiles()
@ -435,7 +435,7 @@ class CityScreen(
} }
fun exit() { fun exit() {
game.setWorldScreen() game.resetToWorldScreen()
game.worldScreen.mapHolder.setCenterPosition(city.location) game.worldScreen.mapHolder.setCenterPosition(city.location)
game.worldScreen.bottomUnitTable.selectUnit() game.worldScreen.bottomUnitTable.selectUnit()
} }

View File

@ -120,8 +120,7 @@ class OptionsPopup(
private fun reloadWorldAndOptions() { private fun reloadWorldAndOptions() {
settings.save() settings.save()
if (screen is WorldScreen) { if (screen is WorldScreen) {
screen.game.worldScreen = WorldScreen(screen.gameInfo, screen.viewingCiv) screen.game.resetToWorldScreen(WorldScreen(screen.gameInfo, screen.viewingCiv))
screen.game.setWorldScreen()
} else if (screen is MainMenuScreen) { } else if (screen is MainMenuScreen) {
screen.game.setScreen(MainMenuScreen()) screen.game.setScreen(MainMenuScreen())
} }

View File

@ -44,7 +44,7 @@ class EmpireOverviewScreen(
else game.settings.lastOverviewPage else game.settings.lastOverviewPage
val iconSize = Constants.defaultFontSize.toFloat() val iconSize = Constants.defaultFontSize.toFloat()
onBackButtonClicked { game.setWorldScreen() } onBackButtonClicked { game.resetToWorldScreen() }
tabbedPager = TabbedPager( tabbedPager = TabbedPager(
stage.width, stage.width, stage.width, stage.width,
@ -54,7 +54,7 @@ class EmpireOverviewScreen(
capacity = EmpireOverviewCategories.values().size) capacity = EmpireOverviewCategories.values().size)
tabbedPager.bindArrowKeys() tabbedPager.bindArrowKeys()
tabbedPager.addClosePage { game.setWorldScreen() } tabbedPager.addClosePage { game.resetToWorldScreen() }
for (category in EmpireOverviewCategories.values()) { for (category in EmpireOverviewCategories.values()) {
val tabState = category.stateTester(viewingPlayer) val tabState = category.stateTester(viewingPlayer)

View File

@ -74,7 +74,7 @@ class ResourcesOverviewTab(
ImageGetter.getResourceImage(name, iconSize).apply { ImageGetter.getResourceImage(name, iconSize).apply {
onClick { onClick {
if (viewingPlayer.gameInfo.notifyExploredResources(viewingPlayer, name, 0, true)) if (viewingPlayer.gameInfo.notifyExploredResources(viewingPlayer, name, 0, true))
overviewScreen.game.setWorldScreen() overviewScreen.game.resetToWorldScreen()
} }
} }
private fun TileResource.getLabel() = name.toLabel().apply { private fun TileResource.getLabel() = name.toLabel().apply {

View File

@ -68,7 +68,7 @@ class UnitOverviewTab(
private fun showWorldScreenAt(position: Vector2, unit: MapUnit?) { private fun showWorldScreenAt(position: Vector2, unit: MapUnit?) {
val game = overviewScreen.game val game = overviewScreen.game
game.setWorldScreen() game.resetToWorldScreen()
game.worldScreen.mapHolder.setCenterPosition(position, forceSelectUnit = unit) game.worldScreen.mapHolder.setCenterPosition(position, forceSelectUnit = unit)
} }
private fun showWorldScreenAt(unit: MapUnit) = showWorldScreenAt(unit.currentTile.position, unit) private fun showWorldScreenAt(unit: MapUnit) = showWorldScreenAt(unit.currentTile.position, unit)

View File

@ -238,7 +238,7 @@ class WonderOverviewTab(
val locationLabel = locationText.toLabel() val locationLabel = locationText.toLabel()
if (wonder.location != null) if (wonder.location != null)
locationLabel.onClick{ locationLabel.onClick{
UncivGame.Current.setWorldScreen() UncivGame.Current.resetToWorldScreen()
UncivGame.Current.worldScreen.mapHolder.setCenterPosition(wonder.location.position) UncivGame.Current.worldScreen.mapHolder.setCenterPosition(wonder.location.position)
} }
add(locationLabel).fillY() add(locationLabel).fillY()

View File

@ -30,7 +30,7 @@ class DiplomaticVotePickerScreen(private val votingCiv: CivilizationInfo) : Pick
rightSideButton.onClick(UncivSound.Chimes) { rightSideButton.onClick(UncivSound.Chimes) {
votingCiv.diplomaticVoteForCiv(chosenCiv!!) votingCiv.diplomaticVoteForCiv(chosenCiv!!)
UncivGame.Current.setWorldScreen() UncivGame.Current.resetToWorldScreen()
} }
} }

View File

@ -25,7 +25,7 @@ class DiplomaticVoteResultScreen(val votesCast: HashMap<String, String>, val vie
rightSideButton.onClick(UncivSound.Click) { rightSideButton.onClick(UncivSound.Click) {
viewingCiv.addFlag(CivFlags.ShowDiplomaticVotingResults.name, -1) viewingCiv.addFlag(CivFlags.ShowDiplomaticVotingResults.name, -1)
UncivGame.Current.setWorldScreen() UncivGame.Current.resetToWorldScreen()
} }
rightSideButton.enable() rightSideButton.enable()
rightSideButton.setText("Continue".tr()) rightSideButton.setText("Continue".tr())
@ -52,4 +52,4 @@ class DiplomaticVoteResultScreen(val votesCast: HashMap<String, String>, val vie
topTable.add(ImageGetter.getNationIndicator(votedCiv.nation, 30f)).pad(10f) topTable.add(ImageGetter.getNationIndicator(votedCiv.nation, 30f)).pad(10f)
topTable.add(votedCiv.civName.toLabel()).row() topTable.add(votedCiv.civName.toLabel()).row()
} }
} }

View File

@ -37,7 +37,7 @@ class GreatPersonPickerScreen(val civInfo:CivilizationInfo) : PickerScreen() {
civInfo.greatPeople.mayaLimitedFreeGP-- civInfo.greatPeople.mayaLimitedFreeGP--
civInfo.greatPeople.longCountGPPool.remove(theChosenOne!!.name) civInfo.greatPeople.longCountGPPool.remove(theChosenOne!!.name)
} }
UncivGame.Current.setWorldScreen() UncivGame.Current.resetToWorldScreen()
} }
} }

View File

@ -44,13 +44,13 @@ class ImprovementPickerScreen(
unit.action = null // this is to "wake up" the worker if it's sleeping unit.action = null // this is to "wake up" the worker if it's sleeping
onAccept() onAccept()
} }
game.setWorldScreen() game.resetToWorldScreen()
dispose() dispose()
} }
init { init {
setDefaultCloseAction() setDefaultCloseAction()
onBackButtonClicked { UncivGame.Current.setWorldScreen() } onBackButtonClicked { UncivGame.Current.resetToWorldScreen() }
rightSideButton.setText("Pick improvement".tr()) rightSideButton.setText("Pick improvement".tr())
rightSideButton.onClick { rightSideButton.onClick {

View File

@ -42,7 +42,7 @@ open class PickerScreen(disableScroll: Boolean = false) : BaseScreen() {
fun setDefaultCloseAction(previousScreen: BaseScreen?=null) { fun setDefaultCloseAction(previousScreen: BaseScreen?=null) {
val closeAction = { val closeAction = {
if (previousScreen != null) game.setScreen(previousScreen) if (previousScreen != null) game.setScreen(previousScreen)
else game.setWorldScreen() else game.resetToWorldScreen()
dispose() dispose()
} }
pickerPane.closeButton.onClick(closeAction) pickerPane.closeButton.onClick(closeAction)

View File

@ -40,7 +40,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
if (policies.freePolicies > 0 && policies.canAdoptPolicy()) if (policies.freePolicies > 0 && policies.canAdoptPolicy())
closeButton.disable() closeButton.disable()
else else
onBackButtonClicked { UncivGame.Current.setWorldScreen() } onBackButtonClicked { UncivGame.Current.resetToWorldScreen() }
rightSideButton.onClick(UncivSound.Policy) { rightSideButton.onClick(UncivSound.Policy) {
val policy = pickedPolicy!! val policy = pickedPolicy!!
@ -52,7 +52,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
// If we've moved to another screen in the meantime (great person pick, victory screen) ignore this // If we've moved to another screen in the meantime (great person pick, victory screen) ignore this
if (game.screen !is PolicyPickerScreen || !policies.canAdoptPolicy()) { if (game.screen !is PolicyPickerScreen || !policies.canAdoptPolicy()) {
game.setWorldScreen() game.resetToWorldScreen()
dispose() dispose()
} else { } else {
val policyScreen = PolicyPickerScreen(worldScreen) val policyScreen = PolicyPickerScreen(worldScreen)

View File

@ -25,13 +25,13 @@ class PromotionPickerScreen(val unit: MapUnit) : PickerScreen() {
if (unit.promotions.canBePromoted()) if (unit.promotions.canBePromoted())
game.setScreen(PromotionPickerScreen(unit).setScrollY(scrollPane.scrollY)) game.setScreen(PromotionPickerScreen(unit).setScrollY(scrollPane.scrollY))
else else
game.setWorldScreen() game.resetToWorldScreen()
dispose() dispose()
game.worldScreen.shouldUpdate = true game.worldScreen.shouldUpdate = true
} }
init { init {
onBackButtonClicked { UncivGame.Current.setWorldScreen() } onBackButtonClicked { UncivGame.Current.resetToWorldScreen() }
setDefaultCloseAction() setDefaultCloseAction()
rightSideButton.setText("Pick promotion".tr()) rightSideButton.setText("Pick promotion".tr())

View File

@ -61,7 +61,7 @@ abstract class ReligionPickerScreenCommon(
rightSideButton.setText(buttonText.tr()) rightSideButton.setText(buttonText.tr())
rightSideButton.onClick(UncivSound.Choir) { rightSideButton.onClick(UncivSound.Choir) {
choosingCiv.religionManager.action() choosingCiv.religionManager.action()
UncivGame.Current.setWorldScreen() UncivGame.Current.resetToWorldScreen()
dispose() dispose()
} }
} }

View File

@ -57,7 +57,7 @@ class TechPickerScreen(
init { init {
setDefaultCloseAction() setDefaultCloseAction()
onBackButtonClicked { UncivGame.Current.setWorldScreen() } onBackButtonClicked { UncivGame.Current.resetToWorldScreen() }
scrollPane.setOverscroll(false, false) scrollPane.setOverscroll(false, false)
descriptionLabel.onClick { descriptionLabel.onClick {
@ -83,7 +83,7 @@ class TechPickerScreen(
game.settings.addCompletedTutorialTask("Pick technology") game.settings.addCompletedTutorialTask("Pick technology")
game.setWorldScreen() game.resetToWorldScreen()
game.worldScreen.shouldUpdate = true game.worldScreen.shouldUpdate = true
dispose() dispose()
} }

View File

@ -63,7 +63,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : PickerScreen(disableScroll = true
launchCrashHandling("SaveGame", runAsDaemon = false) { launchCrashHandling("SaveGame", runAsDaemon = false) {
GameSaver.saveGameToCustomLocation(gameInfo, gameNameTextField.text) { e -> GameSaver.saveGameToCustomLocation(gameInfo, gameNameTextField.text) { e ->
if (e == null) { if (e == null) {
postCrashHandlingRunnable { game.setWorldScreen() } postCrashHandlingRunnable { game.resetToWorldScreen() }
} else if (e !is CancellationException) { } else if (e !is CancellationException) {
errorLabel.setText("Could not save game to custom location!".tr()) errorLabel.setText("Could not save game to custom location!".tr())
e.printStackTrace() e.printStackTrace()
@ -101,7 +101,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : PickerScreen(disableScroll = true
GameSaver.saveGame(gameInfo, gameNameTextField.text) { GameSaver.saveGame(gameInfo, gameNameTextField.text) {
postCrashHandlingRunnable { postCrashHandlingRunnable {
if (it != null) ToastPopup("Could not save game!", this@SaveGameScreen) if (it != null) ToastPopup("Could not save game!", this@SaveGameScreen)
else UncivGame.Current.setWorldScreen() else UncivGame.Current.resetToWorldScreen()
} }
} }
} }

View File

@ -59,7 +59,7 @@ class DiplomacyScreen(
private fun isNotPlayersTurn() = !UncivGame.Current.worldScreen.canChangeState private fun isNotPlayersTurn() = !UncivGame.Current.worldScreen.canChangeState
init { init {
onBackButtonClicked { UncivGame.Current.setWorldScreen() } onBackButtonClicked { UncivGame.Current.resetToWorldScreen() }
val splitPane = SplitPane(leftSideScroll, rightSideTable, false, skin) val splitPane = SplitPane(leftSideScroll, rightSideTable, false, skin)
splitPane.splitAmount = 0.2f splitPane.splitAmount = 0.2f
@ -68,7 +68,7 @@ class DiplomacyScreen(
splitPane.setFillParent(true) splitPane.setFillParent(true)
stage.addActor(splitPane) stage.addActor(splitPane)
closeButton.onClick { UncivGame.Current.setWorldScreen() } closeButton.onClick { UncivGame.Current.resetToWorldScreen() }
closeButton.label.setFontSize(Constants.headingFontSize) closeButton.label.setFontSize(Constants.headingFontSize)
closeButton.labelCell.pad(10f) closeButton.labelCell.pad(10f)
closeButton.pack() closeButton.pack()
@ -457,7 +457,7 @@ class DiplomacyScreen(
diplomaticMarriageButton.onClick { diplomaticMarriageButton.onClick {
val newCities = otherCiv.cities val newCities = otherCiv.cities
otherCiv.cityStateFunctions.diplomaticMarriage(viewingCiv) otherCiv.cityStateFunctions.diplomaticMarriage(viewingCiv)
UncivGame.Current.setWorldScreen() // The other civ will no longer exist UncivGame.Current.resetToWorldScreen() // The other civ will no longer exist
for (city in newCities) for (city in newCities)
viewingCiv.popupAlerts.add(PopupAlert(AlertType.DiplomaticMarriage, city.id)) // Player gets to choose between annex and puppet viewingCiv.popupAlerts.add(PopupAlert(AlertType.DiplomaticMarriage, city.id)) // Player gets to choose between annex and puppet
} }
@ -937,7 +937,7 @@ class DiplomacyScreen(
private fun getGoToOnMapButton(civilization: CivilizationInfo): TextButton { private fun getGoToOnMapButton(civilization: CivilizationInfo): TextButton {
val goToOnMapButton = "Go to on map".toTextButton() val goToOnMapButton = "Go to on map".toTextButton()
goToOnMapButton.onClick { goToOnMapButton.onClick {
UncivGame.Current.setWorldScreen() UncivGame.Current.resetToWorldScreen()
UncivGame.Current.worldScreen.mapHolder.setCenterPosition(civilization.getCapital().location, selectUnit = false) UncivGame.Current.worldScreen.mapHolder.setCenterPosition(civilization.getCapital().location, selectUnit = false)
} }
return goToOnMapButton return goToOnMapButton

View File

@ -67,7 +67,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
wonOrLost("", null, false) wonOrLost("", null, false)
} else if (!someoneHasWon) { } else if (!someoneHasWon) {
setDefaultCloseAction() setDefaultCloseAction()
onBackButtonClicked { game.setWorldScreen() } onBackButtonClicked { game.resetToWorldScreen() }
} }
} }
@ -95,7 +95,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
closeButton.setText("One more turn...!".tr()) closeButton.setText("One more turn...!".tr())
closeButton.onClick { closeButton.onClick {
gameInfo.oneMoreTurnMode = true gameInfo.oneMoreTurnMode = true
game.setWorldScreen() game.resetToWorldScreen()
} }
} }

View File

@ -19,8 +19,7 @@ class PlayerReadyScreen(gameInfo: GameInfo, currentPlayerCiv: CivilizationInfo)
table.onClick { table.onClick {
postCrashHandlingRunnable { // To avoid ANRs on Android when the creation of the worldscreen takes more than 500ms postCrashHandlingRunnable { // To avoid ANRs on Android when the creation of the worldscreen takes more than 500ms
game.worldScreen = WorldScreen(gameInfo, currentPlayerCiv) game.resetToWorldScreen(WorldScreen(gameInfo, currentPlayerCiv))
game.setWorldScreen()
} }
} }
table.setFillParent(true) table.setFillParent(true)

View File

@ -651,8 +651,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
newWorldScreen.selectedCiv = gameInfo.getCivilization(selectedCiv.civName) newWorldScreen.selectedCiv = gameInfo.getCivilization(selectedCiv.civName)
newWorldScreen.fogOfWar = fogOfWar newWorldScreen.fogOfWar = fogOfWar
game.worldScreen = newWorldScreen game.resetToWorldScreen(newWorldScreen)
game.setWorldScreen()
} }
fun nextTurn() { fun nextTurn() {