i have created a round based card battle system, that could be executed full automatically
private void autoBattle(Battlefield battlefield) {
// don't stop animation on EnemyCardChoose or EnemyTurn
if (automatedBattle ||
battleState == EnumCollection.BattleState.EnemyCardChoose ||
battleState == EnumCollection.BattleState.EnemyTurn) {
if (battleState == EnumCollection.BattleState.CardChoose) {
executeAction(Action.fillHand(), battlefield, true, () -> {
battleState = EnumCollection.BattleState.PlayerTurn;
updateCurrentState();
autoBattle(battlefield);
});
} else if (battleState == EnumCollection.BattleState.PlayerTurn) {
executeAction(Action.turn(), battlefield, true, () -> {
if (battlefield.isBattleEnd()) {
if (battlefield.hasWon(battlefield.getUser())) {
battleState = EnumCollection.BattleState.Victory;
} else {
battleState = EnumCollection.BattleState.Defeat;
}
} else {
battleState = EnumCollection.BattleState.EnemyCardChoose;
}
updateCurrentState();
autoBattle(battlefield);
});
} else...
}
}
in executeAction
i:
check the played cards
make animations
update the values
calls the finish callback, that executes autoBattle
again
The problem is, that repeated execution of autoBattle
is called from callback, means - the stack is ever grows.
With all the animations the filling of ram comes quick from 170 MB to 300 MB and over.
What is the proper way to execute the loop, with animations that takes a time, and let garbage collector working?
solved by creation of Runnable
and Handler
as global variabled after generation of battlefield
Handler handler = new Handler();
Runnable runnable = () ->
autoBattle(battlefield);
and calling handler.postDelayed(runnable, 30);
instead of autoBattle(battlefield);
With that way every 60 MB the RAM was freed and 300 MB was not reached by over 300 loops every cleaning started by 220 MB