1

I am using Canvas in my android game. When I remove a no longer displayed entity in my entity list, all other entities are flickering for a brief time. When it's not removed, there is no such problem. But since I am not a big fan of memory leaks, that's not an option.

The canvas rendering system is already double-buffered by design and I have utterly no idea how to fix such a problem. I have thought maybe it is because the list is sorting itself after the item removal and tried changing it to a Set, but that didn't work either.

Does anyone have any idea why this might be happening and how to fix it?

Structure of the code:

private val gameObjects: List<GameObject> = mutableListOf()
    
    fun update(deltaTime: Long)
    {
        gameObjects.forEach {
            it.update(deltaTime)
    }

 fun render(canvas: Canvas)
    {
      gameObjects.forEach {
         when (getVisibilityStatus(it.virtualY))
         {
            VisibilityStatus.VISIBLE -> it.render(canvas, virtualToPhysicalY(it.virtualY))

            VisibilityStatus.BELOW_SCREEN ->
            {
              if (virtualToPhysicalY(it.virtualY) > screenSizePairXY.second)
                gameObjects.remove(it)
            
            }
         }
    }
DeveloperKurt
  • 758
  • 1
  • 7
  • 21

1 Answers1

2

Removing elements from list you iterating its not safe practice. It would be better to do culling (removing invisible elements) before drawing cycle in separate cycle. Here is some explanation:

Remove elements from collection while iterating

Bolat Basheyev
  • 191
  • 2
  • 9
  • The list is only modified and accessed by the game thread. – DeveloperKurt Sep 01 '20 at 03:49
  • A little bit unclear to me. Can you post some drawing & entity removing code? – Bolat Basheyev Sep 01 '20 at 03:55
  • The game loop and rendering happens in the same thread. To draw, canvas.drawBitmap() method is called and when the entity is no longer visible merely the list.remove() method is getting called to let the garbage collector do its work. I edit my post and post an example of it in 5 minutes. – DeveloperKurt Sep 01 '20 at 04:00
  • 2
    You are deleting entities in the same cycle with drawing. Its NOT SAFE practice to remove elements from list you iteraing. Do your culling (removing invisible elements) before drawing cycle in separate cycle. Or mark them as invisible. – Bolat Basheyev Sep 01 '20 at 04:29
  • Can you elaborate on why is that? Why it isn't safe? – DeveloperKurt Sep 01 '20 at 04:35
  • https://stackoverflow.com/questions/10431981/remove-elements-from-collection-while-iterating – Bolat Basheyev Sep 01 '20 at 04:39
  • 2
    https://stackoverflow.com/questions/1196586/calling-remove-in-foreach-loop-in-java – Bolat Basheyev Sep 01 '20 at 04:42
  • Thank you, separating the cleanup operation from the for each loop fixed the issue. Please state that clearly by editing your answer so I can accept it. – DeveloperKurt Sep 01 '20 at 06:00