Bitmaps and "Out of memory error"

socialnetis

Active Member
Licensed User
Longtime User
Hi, I'm developing an App in which I download some pictures from a web (using httputils2), and then display it in the screen.

First, I download the Page (its a feed, so is an xml file), and parse it to have the links of the images (there are like 40 images). I have a List, which adds pairs of this links and a bitmap (which is empty at first).

Then, I download the first picture, and add the bitmap to the List, and display it to the user.

And then, it follows like this: While there is an image on the screen, the next image is beeing downloaded.

The idea is that the user can go forward and backward to see any image.

The problem that I'm having is that in about the image number 10 or more, I get an "Out of memory error". I guess that its about having lots of bitmap on ram. How can I manage this? I know that I can write to disk, but they will continue in ram I guess.
 

sorex

Expert
Licensed User
Longtime User
I didn't work with something like that before so I'm amazed it runs out of memory so fast

but I guess this is the way to go

load your list of links
download picture 1 & save to app/sd folder
display picture 1
download picture 2 & save to app/sd folder
display picture 2
remove picture 1 view
download picture 3 & save to app/sd folder
display picture 3
remove picture 2 view

you can add a fileexist check to prevent re-downloading an image to speed things up.

if you display several images on screen you'll need to remove what goes off screen and add what will appear.

it might be tricky to code but it's the only way to solve such issues I guess.

maybe you just need to optimize your pictures a bit (640x480/72dpi max)
as they might be in a too big resolution (150-300+ dpi) ?
 
Upvote 0

eps

Expert
Licensed User
Longtime User
Without seeing any of your code it's almost impossible to give good advice.

How are you loading the files?

What format are they in?

What size are they?

What are the capabilities of the device you are using?

How are you initialising the Canvas to display the images?

Have you attempted to indicate that when you display image 3 or so, that the memory occupied by image 1 can be recycled by Android?

etc...
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Search the forum for "bitmap recycle" and you'll see there are code examples that show how to try to free up memory in use by Bitmaps that are no longer required.

Martin.
 
Upvote 0

socialnetis

Active Member
Licensed User
Longtime User
Ok, I think that I have manage the problem. The Tuple objects now holds a Boolean indicating if the Image have been downloaded or not, instead of the bitmap.
And now, for every downloaded Image, I write it into the SD card. And when I want to display it, I just read it.

How are you loading the files?
I get the bitmap from a HttpJob download, and then put the bitmap into an imageView to display it.

What format are they in?
They are JPEG files

What size are they?
There are many sizes, but they are all about 30-100kb

What are the capabilities of the device you are using?
I'm using a Motorola Defy, with a 1ghz micro and 512mb ram.

How are you initialising the Canvas to display the images?
I have no canvas, I use a ImageView

Have you attempted to indicate that when you display image 3 or so, that the memory occupied by image 1 can be recycled by Android?
I'm not using any code to indicate directly to Android to recycle, but I read that when you lose the reference to a bitmap, the garbage collector should recycle it.

So, here is the important code:

B4X:
Sub Show_Image
   Dim h,w,aux As Double
   Dim bmp As Bitmap
   Dim mTuple As Tuple                'Tuple is an obj that holds a Title, ImageLink, and a Boolean that says if the Image have been downloaded or not
   Dim Pz As PinchZoomAndMove
   
   mTuple = mList.Get(Visor)            'I get the Info from the Image I wanna see 
   bmp.Initialize(File.DirDefaultExternal,Visor)        'Initialize the bitmap, at this point, the previous Image I was seeing,
                                                                        'should have been recolected by the garbace collector
   h = bmp.Height
   w = bmp.Width
   If Not(Image.IsInitialized) Then        'Image is a ImageView, its a global variable.
      Image.Initialize("mImage")
   End If
   Image.RemoveView
   Image.Bitmap = bmp                      'At this point there is not reference at all to the previous Bitmap
   Image.Gravity = Gravity.FILL
   aux = (h/w)*Panel1.Width
   Panel1.AddView(Image,0,Panel1.Height/2-aux/2,100%x,aux)
   prev_image.BringToFront                'This are bottons to se the previous and next Image
   next_image.BringToFront

   Pz.Initialize(Image,"PZ",Image.Tag,1,3,1.5,False,Me)        'This is to pinch and zoom
   Pz.SetLimitArea(True)
   Activity.Title = (mTuple.Title)
   
   If Not(Lock) Then                        'I download 1 Image at the time on demand. DownloadNextImage puts a lock which is released when the Image is actually downloaded
      DownloadNextImage
   Else
      Timer1.Enabled = True          'The Timer will ask every 0.5s if the Lock is released
   End If
End Sub

PS. sorry for the un-tab comments of the code, I have just added in this post, I don't have them on the project
 
Upvote 0

FJS

Active Member
Licensed User
Longtime User
good afternoon,

I have the same problem: the next message appear when I go to an activity and it is not the firsttime
"java.lang.OutOfMemoryError"

How I can erase the bitmaps, or free memory?
I use bitmapdata, with gameviews and also I use imageview, as example:

puntuacion.Bitmap=IU.LoadScaledBitmap(File.DirAssets,"score_330x110.png",330*a*x,110*a*x,True)
ImageView3.Bitmap=LoadBitmapSample(File.DirAssets,"start_410x150.png",Activity.Width,Activity.Height)

Please, I need help to fix it. when i go from a activity to other, nothing happen, (when the userclosed=false), but when I push the return of my movil then userclosed=true, and when I try to comeback to the activity, the message appears

Thank you for your help,

Best regards
 
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Good afternoon Erel,

First of all, thank you for your support like always.
In the past, I had a problem with the quality of the bitmap, so I use the loadscalebitmap, because it works better. On the other hand, the caching the bitmaps in a process global does not work, sorry.
I read in other forum other solutions: use Initialize2, or use one library?
This situation only happen with my tablet asus transformer (it is not bad regarding memory, so I cant understand)
How I can erase the bitmaps, or free memory?

When I use activity.finish and I resume the activity says isfirst=false, but I would like isfirst=true, how can I do it?
Thank you again

Best regards
 
Last edited:
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Good morning Erel,

Please could you give us several examples where the images are loading and when the images are using the cached images?
It is not clear for me how to do it

Thank you
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Small example:
B4X:
Sub Process_Globals
   Private bitmapsCache As Map
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
     bitmapsCache.Initialize
     bitmapsCache.Put("image1", LoadBitmapSample(...))
     bitmapsCache.Put("image2", LoadBitmapSample(...))
     bitmapsCache.Put("image3", LoadBitmapSample(...))
     bitmapsCache.Put("image4", LoadBitmapSample(...))
   End If
   ImageView1.SetBackgroundImage(bitmapsCache.Get("image1"))
End Sub
 
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Good afternoon Erel,

Now when the activity is isfirst=true, the error"out of the memory" appears!, it seems that the application can not load all the bitmap at the same time (there are many, around 50 or 60 pictures), some bitmap with loadbitmapsample and other with LoadScaledBitmap (because it has better quality as you know)

Sorry, but is not there any way to free memory when you push backbotton, when you finish the activity...

I have just checked that when userclosed=true the problem appears as well...

I supose many people has to have the same problems with tablets (in my phone is ok!)

thank you for your support, I need your help in this topic!
 
Last edited:
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Good afternoon Erel,

I have just cheched, and the image are between 8 and 100kb not more ( the mayority of them are around 30kb)
Please could you tell us how use reflection library with gv.??

B4X:
  gv.Initialize("gv")

            Activity.AddView(gv, 0, 0, 100%x, 100%y)

            AcSf.Initialize("AcSf", True)
            Activity.AddView(AcSf, 0, 0, 100%x, 100%y)
          
                gv.BitmapsData.Add(fondo)
                gv.BitmapsData.Add(background)
                gv.BitmapsData.Add(puntuacion)
              
                For i=0 To 2
                    gv.BitmapsData.Add(Mtimedraw(i))
                Next
              
                gv.BitmapsData.Add(fondowhite)
              
                For i=0 To 4
                    gv.BitmapsData.Add(Mscoredraw(i))
                Next
              
                gv.BitmapsData.Add(tittle)
          
                gv.BitmapsData.Add(number3)
              
                '  bitmaps
              
                For i=0 To 1
                For j=0 To 1
                  gv.BitmapsData.Add(M22draw(i,j))
                  gv.BitmapsData.Add(M22drawb(i,j))
                Next          
                Next
              
                For i=0 To 2
                For j=0 To 2
                  gv.BitmapsData.Add(M33draw(i,j))
                  gv.BitmapsData.Add(M33drawb(i,j))
                Next
                Next
              
                For i=0 To 3
                For j=0 To 3
                  gv.BitmapsData.Add(M44draw(i,j))
                  gv.BitmapsData.Add(M44drawb(i,j))
                Next
                Next
                    
                For i=0 To 2
                    gv.BitmapsData.Add(lifes(i))
                Next
                gv.BitmapsData.Add(checkdraw)
                gv.BitmapsData.Add(levelicon)
                gv.BitmapsData.Add(recordicon)
              
                For i=0 To 4
                    gv.BitmapsData.Add(Msumadraw(i))
                Next
              
                For i=0 To 4
                    gv.BitmapsData.Add(Mtimeaddraw(i))
                Next
              
            If gv.IsHardwareAccelerated = False Then
                Msgbox("Hardware acceleration is not supported!!!", "")
            End If
          

    Activity.LoadLayout("game31")


playagain=0

x=Activity.Width/100.0
y=Activity.Height/100.0

ho=(Activity.Height-50.0+104.0*x*2.0)*0.32

If (language="EN") Then
    a=0.18  
    puntuacion.Bitmap=IU.LoadScaledBitmap(File.DirAssets,"score_330x110.png",330*a*x,110*a*x,True)
    ImageView3.Bitmap=LoadBitmapSample(File.DirAssets,"start_410x150.png",Activity.Width,Activity.Height)
    ImageView6.Bitmap=LoadBitmapSample(File.DirAssets,"Pausepanel_620x590.png",Activity.Width,Activity.Height)
    a=0.16
    tittle.Bitmap= IU.LoadScaledBitmap(File.DirAssets,"theyareequal_320x40.png",320*a*x,40*a*x,True)
    fondowhite.Bitmap=IU.LoadScaledBitmap(File.DirAssets,"gameoverpanele_620x590.png",620*x*0.155,590*x*0.155,True)
End If
If (language="ES") Then
    a=0.18  
    puntuacion.Bitmap=IU.LoadScaledBitmap(File.DirAssets,"puntuacion_330x110.png",330*a*x,110*a*x,True)
    ImageView3.Bitmap=LoadBitmapSample(File.DirAssets,"empezar_410x150.png",Activity.Width,Activity.Height)
    ImageView6.Bitmap=LoadBitmapSample(File.DirAssets,"Pausapanel_620x590.png",Activity.Width,Activity.Height)
    a=0.16
    tittle.Bitmap= IU.LoadScaledBitmap(File.DirAssets,"soniguales_320x40.png",320*a*x,40*a*x,True)
    fondowhite.Bitmap=IU.LoadScaledBitmap(File.DirAssets,"gameoverpanels_620x590.png",620*x*0.155,590*x*0.155,True)
End If

......
 
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Good afternoon Erel,

I have two questions:

1- I have tried to use "recycle", like this

Dim Obj1 As Reflector
Obj1.Target=puntuacionini
Obj1.RunMethod("recycle")
where puntuacionini is a bitmapdata, but it doesnot work, Do you know why?

2- Please could you give us any "gold rules" to create apps and games and save memory??, is there any information in the forum??

For example, when we waste memory, when "Dim bitmap1 as bitmapdata" or when i load the file??

Thank you very much for your help like always:)
 
Upvote 0
Top