Out of Memory Exception with bitmap

rmoore

Member
Licensed User
Longtime User
I have been getting Out of Memory Exceptions, which I am pretty certain are due to my using a large bitmap. I am creating this bitmap by drawing on the canvas cvs.

My first solution I found on this forum. I put this code in my Activity_Pause routine:
B4X:
Obj1.Target = cvs
Obj1.Target = Obj1.GetField("bw")
Obj1.Target = Obj1.RunMethod("getObject")
Obj1.RunMethod("recycle")
This helped to reduce the occurrence of the error, but I realized that I was redrawing my canvas many times between each call of Activity_Pause, and was probably creating many bitmaps in the process, and so decided to recycle the bitmap before each redrawing. But when I initialized the canvas following the recycle code above, I would get the error "Trying to use a recycled bitmap".

So I set the canvas to null after every recycle, so that a new bitmap would have to be recreated.
B4X:
Obj1.Target = cvs
Obj1.Target = Obj1.GetField("bw")
Obj1.Target = Obj1.RunMethod("getObject")
Obj1.RunMethod("recycle")
cvs = null
But this gave me an Java Null Exception error when I tried to reinitialize the canvas.

I am pretty new to b4a, and I thought that initialize would create a new object under any circumstances, either immediately after the dim or at any time later, but I am obviously missing something basic, since I wrote the following code which highlights my problem.
B4X:
cvs.Initialize(ivB)   '  OK
cvs = Null
cvs.Initialize(ivB)   ' Java Null Exception

Help from the experts, please!

Ron
 

rmoore

Member
Licensed User
Longtime User
Erel,

Thanks for the quick response.

My program actually only has one bitmap image, and I am not certain that I am creating many bitmaps, but I am zooming my canvas and this involves redrawing it, and I guess that I may be creating many bitmaps in the process.

Because I continue to experience Out of Memory errors, I am thinking that I may be recreating the bitmap associated with the canvas.

I may not be zooming in the most efficient manner, but it works fine and fast except that it eventually leads to an Out of Memory error.

I would appreciate any comments you have on the Java null pointer exception that I am getting when I try to initialize a null canvas.

Ron
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
I think that you are not trying to initialize a canvas, but a null object :)
I would redim before trying to initialize, and please note that no reDim exists, you simply dim again.
 
Upvote 0

rmoore

Member
Licensed User
Longtime User
mc73,

Thanks! That makes perfect sense! However, I will have to think about how I am going to redim (dim) the canvas as the canvas needs to be global.

Ron
 
Upvote 0

rmoore

Member
Licensed User
Longtime User
Erel,

I have attached a zip of my project. Please note that it is a work-in-progress, very much incomplete, and I am trying to get to the bottom of the Out-of-Memory exceptions before proceeding further.

You can get the OOM exception by two-finger-zooming the board to maximum (3 times the original size), un-zooming then re-zooming. I am quite prepared to find that my code is causing the problem, but perhaps you can throw some light on why the bitmap recycling isn't effective in this case (of course it may not be related to bitmaps at all!).

Could you also comment on this earlier post on this subject by mc73?
I think that you are not trying to initialize a canvas, but a null object :)
I would redim before trying to initialize, and please note that no reDim exists, you simply dim again.

Ron
 

Attachments

  • Sudoku!.zip
    16.3 KB · Views: 229
Upvote 0

rmoore

Member
Licensed User
Longtime User
Erel,

OK, I'll look into this. I originally did not reinitialize the canvas before each redrawing, but I hit some problems, and, being new to b4a, decided that I needed to re-initialize the canvas, and this solved my problems at that time. I don't remember what the problems were, but I am more familiar with b4a now and may be able to solve them differently. I am eager to get this working without re-initializing the canvas, as I expect that it would run even faster!

I would still like your comments on why I can't recycle my bitmap successfully, and why I can't initialize a null canvas. Please bear in mind that I am still fairly new to b4a and may be unaware of some basics.

Thanks for your help.

Ron
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
In most cases it is not required to recycle the bitmaps yourself. It will eventually happen by the garbage collector. The problem in your code is that you only recycle one bitmap when the activity is paused. However you created many many bitmaps during the resize cycle.

B4X:
cvs = Null
cvs.Initialize(ivB)
It is not required to set objects to Null. You need to call Dim again before you can access the canvas.
 
Upvote 0

rmoore

Member
Licensed User
Longtime User
Erel,

I removed the canvas re-initializations from my program as you suggested and then realized why I had introduced them in the first place. As I zoomed, the imageview was expanding too much and was overflowing the containing panel, causing the edges of the image to be lost.

But your replies had given me the will to go on and investigate! I eventually realized that I had been re-drawing the image to match the zoomed size of the imageview, but I now know that the bitmap size does not change as the imageview is zoomed, so I needed to redraw it the same size as it was initially, before any zoom.

Now, not only has the OOM error been laid to rest, but everything runs even faster than before! The only very minor disadvantage is that the zoomed image loses a little resolution.

It all seems obvious now, but for a b4a newbie it wasn't so easy!

Thanks for all your help and your quick responses. I wonder how you ever have time for the many developments that regularly appear!

Keep up the good work!

Ron
 
Upvote 0
Top