Android Question Bitmap and memory management - best practices

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
I've searched the forums for solutions to the "out of memory" problems when dealing with large bitmaps and I seen as many solutions as there are questions.

Let's say I wish to create a game board with squares like a chess board that will have sprites moving on the board and I wish to be able to zoom in and out. For this example let's make the board squares 100dip x 100dip. For a chess sized board that's 800*800*4 or roughly 2.6MB for the entire bitmap. Since each square of the board could have a different background image, redrawing the entire board every single frame is too CPU intensive even on a real device.

I've written similar things in .NET, and to do so I would make two bitmaps, a static "board" bitmap (whch is updated infrequently as the background "square" changes) and a secondary "sprite" bitmap that overlays the board, both of which are drawn at 100% and then scaled to zoom-factor when drawn onto a 3rd "surface" bitmap that is the one being rendered to the user.

Taking this same approach with B4A, when testing on an AVD I generally get an out-of-memory error when I attempt to InitializeMuteable on the 2nd bitmap, let alone a 3rd.

What is the best way (or even a way) to present a large bitmap with animated sprites to the user, while still allowing them to scroll/zoom the final image? Or do I have to settle for one or the other?

Any and all suggestions are welcome :)

Thanks,
- Richard
 

WAZUMBi

Well-Known Member
Licensed User
Longtime User
For most of my apps they all follow the same general pattern:

I use a panel for the background which may or may not be static.

Another panel on top of that. I use a canvas to draw the squares or any static sprites.
I suppose on this panel for a chessboard you would need 64 views scaled to fit the screen.
The background for each view would only need to point to 2 bitmaps however.
I am thinking for this you probably don't need any views anyways for chess.
Just a scaled image of a chessboard.

A third panel on top of that using gameview for the animations.
Draw the chess pieces with gameview on this panel.
Again here you would only need 12 bitmaps and 32 views (for chess) in memory for the pieces.

I've personally used upwards of 1500+ views in a single app. My nonogram app alone uses upto 1369 on the gameboard.

I don't know if this is the best approach but it's simple and works for me with no memory issues reported (so far :)).
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
For most of my apps they all follow the same general pattern:

I use a panel for the background which may or may not be static.

Another panel on top of that. I use a canvas to draw the squares or any static sprites.
I suppose on this panel for a chessboard you would need 64 views scaled to fit the screen.
The background for each view would only need to point to 2 bitmaps however.
I am thinking for this you probably don't need any views anyways for chess.
Just a scaled image of a chessboard.

A third panel on top of that using gameview for the animations.
Draw the chess pieces with gameview on this panel.
Again here you would only need 12 bitmaps and 32 views (for chess) in memory for the pieces.

I've personally used upwards of 1500+ views in a single app. My nonogram app alone uses upto 1369 on the gameboard.

I don't know if this is the best approach but it's simple and works for me with no memory issues reported (so far :)).

Erel - You don't really need an app, just start a new project, add two bitmaps to the globals and then in the activity create:

B4X:
Bitmap1.InitializeMuteable(900dip, 900dip)
Bitmap2.InitializeMuteable(900dip, 900dip)
And see if you have any issues. If you don't then change the phone orientation and you will. The AVD I'm using represents a generic Gingerbread phone (I used the defaults when creating it so 512 RAM with 32 for the VM heap). I even tried rendering the background and saving it to disk then loading it to the bitmap as my "erase" to save time, but I would get the "downsampling....low memory" message in the log every time I passed through my redraw timer.

WASUMBi - So, you're saying that 64 ImageViews, each pointing to two 100dip x 100dip bitmaps will not cause a memory issue, but two 800x800 bitmaps does? o_O Do you create a new canvas each time you need to draw on one of the bitmaps, or do you create one per bitmap and save it along with the bitmap? I was under the impression that creating the canvas each time forced it to use more memory (at least temporarily)?

The app will be more of a tile fill-in game rather than a chess game, I used the chess game only to provide the board analogy. Since it is a tile game, each "square" will have a different bitmap eventually, and there will be no more than eight game pieces that would need to be animated across the squares (and possibly one or two animations in empty squares for any type of "bonus" score squares or something like that).

Thank you both for your replies, I'll have to create a test program with a crazy number of views :D

- Richard
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
Ok, I've created a small test program using 64 views with individual bitmaps, and it creates them with no problems.

I maintain a reference to the "background" panel canvas and draw to that to provide a border and background color. It renders as expected initially at 100%, but when I change the zoom factor the background color drawing is acting as if the panel dimensions were still at 100%.

I thought that may be because I was keeping a reference to the canvas, but when I create the canvas reference on the fly it will give an out of memory error on the Canvas.Initialize(panel). And this is before I've even created a sprite panel to overlay the background (or individual sprites panels).

I have attached the sample project, if you have the time and are so inclined, I would love to see the optimal way of achieving my desired result.

Thanks in advance,
- Richard
 

Attachments

  • BoardTest.zip
    17.5 KB · Views: 248
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
Correct me if I'm wrong, but if you use the same bitmap in different views, and change the bitmap does it not change in all controls?
 
Upvote 0
Top