Bitmaps and "Out of memory error"

Discussion in 'Android Questions' started by socialnetis, Mar 2, 2013.

  1. socialnetis

    socialnetis Active Member Licensed 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.
     
  2. sorex

    sorex Expert Licensed 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) ?
     
  3. eps

    eps Well-Known Member Licensed 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...
     
  4. warwound

    warwound Expert Licensed 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.
     
  5. socialnetis

    socialnetis Active Member Licensed 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.

    I get the bitmap from a HttpJob download, and then put the bitmap into an imageView to display it.

    They are JPEG files

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

    I'm using a Motorola Defy, with a 1ghz micro and 512mb ram.

    I have no canvas, I use a ImageView

    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:

    Code:
    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(LockThen                        '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
     
  6. FJS

    FJS Active Member Licensed 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
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    Try to use LoadBitmapSample instead of LoadScaledBitmap. You can also cache the bitmap in a process global variable instead of loading it each time the activity is created.
     
  8. FJS

    FJS Active Member Licensed 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: Aug 21, 2013
  9. Erel

    Erel Administrator Staff Member Licensed User

    IsFirst will only be True when the process starts. If the issue happens when you change the device orientation then you can solve it by reusing the loaded images (caching the images). You should make sure that you are not loading the images instead of using the cached images.
     
  10. FJS

    FJS Active Member Licensed 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
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    Small example:
    Code:
    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
     
  12. FJS

    FJS Active Member Licensed 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: Aug 23, 2013
  13. Erel

    Erel Administrator Staff Member Licensed User

    You can recycle bitmaps with the reflection library. However I recommend you to first make sure that you are not loading any huge images. Can you post the code that calls LoadScaledBitmap?
     
    Blanko likes this.
  14. FJS

    FJS Active Member Licensed 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.??

    Code:
    gv.Initialize("gv")

                
    Activity.AddView(gv, 00100%x100%y)

                AcSf.Initialize(
    "AcSf"True)
                
    Activity.AddView(AcSf, 00100%x100%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

    ......
     
  15. Erel

    Erel Administrator Staff Member Licensed User

    The image compressed size doesn't matter. It is the actual image size (width * height) that matters.

    You can only recycle images that are no longer used.
     
  16. FJS

    FJS Active Member Licensed 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:)
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    This is a community forum. You should not limit your questions to a single member.

    Please start a new thread for this question.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice