Memory Impact of Canvas

Bill Norris

Active Member
Licensed User
Longtime User
I am tweaking parts of my code to eliminate an outofmemory error. In another post, I was advised this can be attributed to bitmaps. That appears to be the case, as I resolved the problem by removing imageviews with large bitmaps when that activity finishes. I also employ canvas objects on several activities, ONLY for the measurestringwidth function. I have alot of labels on scrollviews, and most are created with width being the same as the scrollview. When the labels are selected and the "selected" color is set, I don't want the entire width of the label to change color, as it looks odd to me to have this wide label highlighted if the text is very short. that being said, I resize each label as they are added using the measurestringwidth, as stated before. To make a long question short, how much memory are those canvas objects consuming? I can live without it but employing it really makes things look better. Is it possible to "un-initialize" a canvas object when the activity closes?
 

Bill Norris

Active Member
Licensed User
Longtime User
RE:

When I first started using the canvas object, I was initializing it to activity, but I've since realized I can initialize it to just the scrollview that contains the labels I am using measurestringwidth on. Seems to have helped my outofmemory issue.
 
Upvote 0

boten

Active Member
Licensed User
Longtime User
I Think I have the "same" problem.
I need a canvas that spans the entire screen. The canvas is used to draw on various panels (each is the size of the screen). The same canvas is "re"-initialized every time for a different panel.
There was no problem when working on 480x800 device, but the same prog crashed on a 1280x800 device.
The error was:

B4X:
java.lang.OutOfMemoryError
   at android.graphics.Bitmap.nativeCreate(Native Method)
   at android.graphics.Bitmap.createBitmap(Bitmap.java:605)
   at android.graphics.Bitmap.createBitmap(Bitmap.java:585)
   at anywheresoftware.b4a.objects.drawable.CanvasWrapper.Initialize(CanvasWrapper.java:72)

and it happened on a cvs.initialize(pnl)

The most strange thing is that it NEVER happened on the first run.
Only on the 2nd time the program was run did it happened. Of course, when it happened, the program crashed, thus is was removed from memory. So the 3rd time was a clean start (like the 1st) and it crashed on the 4th run (like the 2nd).

From Erel's answer I guess this is related to a bigger canvas, but is it possible that ICS (on the bigger device) handles canvases differently?
 
Upvote 0

boten

Active Member
Licensed User
Longtime User
Actually the canvases are initialized on the entire panel/screen to draw lines on the panel.
Since the lines spans both hor/ver to the entire screen width/height, the canvas has to encompass the entire screen.

As a "dirty solution" (and I don't like it a bit) I now use Imageviews (wide & small or tall & thin) and fill them with solid color - I hate this solution, but is there any way to drawlines beside using a canvas?


The larger the bitmap used by the canvas, more memory is required. You should reuse the same bitmap instead of creating new ones all the time.
No bitmaps are used (just a very small one 10x10 to MeasureStringWidth/Height).
I need the canvases to draw lines
 
Upvote 0

boten

Active Member
Licensed User
Longtime User
I think your issue is else where.

The project is very big, no point in attaching it, and trying to replicate the issue in a simple demo project - everything worked.

Well, the error I got was on canvas.initialize(panel) (i used log msgs before & after this stmt. to verify)
The error was memory related (as can be seen from my earlier post)

At first the error occurred in this situation:
I had a full-screen panel, on this panel a long ScrollView, on the scrollview's inner panel a large label (twice the size of full screen). The canvas was init'ed to the very large label.
I realized this was just for StringWidth/Height so I used 10x10 mutablebitmap and a small canvas upon the bitmap to measure.

Then the same error "moved" to another full-screen panel on which I need to draw horizontal & vertical lines all the way to the edges of the screen, so the canvas had to be init'ed to the full-screen panel. This caused the problem.

I know it shouldn't! As u said, 1280x800 is only about 2.6 times bigger than 800x480.

What's more puzzling is that it NEVER happened on a Galaxy S (froyo) and happened very often (every 2nd run) on Asus FT300 (ICS) - same prog of course.
 
Last edited:
Upvote 0

boten

Active Member
Licensed User
Longtime User
Every time you call Canvas.Initialize a bitmap is created with the size of the target view.
So every time i draw something (no pun intended) on a view, a new bitmap is created, even if the same canvas is re-used. Is there a method to get rid of the bitmaps once the drawing is done? ("unload a canvas's related bitmap")?
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime User
Well it does seem to be a border line case, some small memory stuff is pushing it over the limit.
Can you post atleast the Canvas code? Are you Dimming it multiple times or just initializing it? Is it always done in the same routine or multiple places?

Once the Drawing is done and the canvas is released, the bitmap should be released too.
If your canvas is declared as a global variable you would only have one large bitmap loaded in memory.
 
Upvote 0
Top