Android Question How not to waste memory?

FJS

Active Member
Licensed User
Longtime User
Good afternoon,

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 the help like always:)
 

DonManfred

Expert
Licensed User
Longtime User
why you create a new thread for something what you already posted yesterday?. Other threadtitle but the text is nearly the same...
 
Upvote 0

FJS

Active Member
Licensed User
Longtime User
I have focused the "out of memory error" just during the load of the images (it is an your 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

I have used this list of map, but before I finish to load all, the error apears. How can i load the file by steps? during activity_create??

it seems I have too many files, but is there any way to load without this error??

Thank you for all of your help
 
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Hello,

I used two kind of loads:

with loadbitmapsample and LoadScaledBitmap, because the quality of the bitmaps is low some times. Could it affect to the size?
I reduced the activity.wide and antivity.height up to 0.3*activity.wide=maxwide and 0.3*antivity.height=maxheight

Do you (the forum) recommend any other way to load the files? (in order to reduce the used memory?)

Thank you
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
I have focused the "out of memory error" just during the load of the images (it is an your 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

I have used this list of map, but before I finish to load all, the error apears. How can i load the file by steps? during activity_create??

it seems I have too many files, but is there any way to load without this error??

Thank you for all of your help
The first things to do are:
1) Load your images with the correct size. Let's say that their final size on screen is 150x200 pixels, then load them with this size and nothing else. The only function that I know doing that is LoadScaledBitmap in my Accelerated Surface library. The size of the image loaded with LoadBitmapSample is not exactly the size you pass as parameter because the size used internally is the nearest power of two. In some cases, the difference in memory between these two functions is far from being neglectable, especially if you have many images. Another advantage of LoadScaledBitmap is its preservation of the density of the loaded image.
2) Load only the images that you need. If you plan to display an image later, don't load it until it is needed and reuse a bitmap to load it (if possible).

Games created with the libGDX library do not use the Java heap memory space, but the native one, so you have plenty of RAM and Out of Memory errors should not happen. If you really need memory, it's the way to go.
 
Last edited:
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Thank you for your help (both)

Now the bitmaps has the final size, and the files are loaded when the activity is create and it is the first time, but in two packs of loads.

But now the problem is when:
I push the backbutton, the activity A is paused with userclosed=true, then I go to another activity B,
Then I try to go to the first activity A, and just in that momento the following menssage appears: "downsampling image due to lack of memory"

What is happening?
What can I do?
Is possible to put the backbutton unvailable?

Thank you again!!
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
Now the bitmaps has the final size,
I don't think so because you're still using LoadBitmap or LoadBitmapSample ("downsampling image due to lack of memory" is not an error message of LoadScaledBitmap).
And as Erel said, it's a bit strange that your bitmaps are loaded again when you reenter the activity. So, if you do not post your project, I don't think that we will able to help you.
 
  • Like
Reactions: eps
Upvote 0

eps

Expert
Licensed User
Longtime User
Are the bitmaps defined as globals or locally defined?

In order to save memory you need to start off looking to save it, not waste it and then hope that the garbage recycler will be able to help, because if you load lots of images in fairly rapid succession it won't be able to help as it's not that speedy.
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
you load lots of images in fairly rapid succession it won't be able to help as it's not that speedy.
Could you prove it? My UltimateListView creates and destroys a lot of objects, including images, many times per seconds when you scroll it and there's no problem with the GC, at all. On pre-Honeycomb devices, the GC stops your app to do its work, so it cannot be "too slow". The problem was about its triggering in case the device was short on memory and about the bad decisions taken for bitmaps (it couldn't know their size). Since Honeycomb, it doesn't stop your app but its management of unreferenced bitmaps has been improved and the GC is automatically called before an Out of Memory exception is raised so this error cannot happen because the GC is "too slow". This problem of speed is just a myth. Another thing completely untrue that I read many times is the need to call "recycle". It's absolutely useless since Honeycomb. That won't change anything and it's easy to verify with the Monitor tool.

EDIT: in a certain way, yes, we can say there was a problem of speed with the GC under Gingerbread and before because the memory of a bitmap was not freed instantly. When the GC decided to collect bitmaps, it asked to a different process to clean up the native memory and this process could introduce a delay before the job is done. So in some rare cases, you could exceed the memory limit with a new allocation and crashed (the GC was not called again because from its point of view it did its work). If you wanted to mean this, then we agree.
 
Last edited:
  • Like
Reactions: eps
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Thank you for your coments,

Here you can find the main structure of my code (the most important, it is only a summary), I hope it will be enough information
Now the first time, it is ok, but when
I push the backbutton, the activity A is paused with userclosed=true, then I go to another activity B,
Then I try to go to the first activity A(here is the code), and just in that momento the following menssage appears: "downsampling image due to lack of memory"


B4X:
Sub Process_Globals
    Dim BMCplay31 As Map
End Sub

Sub Globals
    'parameters declation:
    Dim ImageView1 As ImageView
    Dim x,y,a,ho As Float
    Dim a1,a2,a3,a4,a5 As Animation
    Dim num As Int
    Dim lifes(3) As BitmapData

      '******************************

    Dim gv As GameView
      Dim AcSf As AcceleratedSurface
    Dim IU As AS_ImageUtils
 
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Activity.LoadLayout("Layout1")

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

         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)

                ' defining the gv and its layouts
                gv.BitmapsData.Add(fondo)

                      '******************************
             
            If gv.IsHardwareAccelerated = False Then
            Msgbox("Hardware acceleration is not supported!!!", "")
            End If
 
 
        '
        Activity.LoadLayout("game31")
         

    ' Load the files only the first time: 
If FirstTime=True Then
     
        BMCplay31.Initialize
        bb=0.3
    a=0.18
        BMCplay31.Put("panelpuntuacion",IU.LoadScaledBitmap(File.DirAssets,"puntuacion_330x110.png",330*a*x,110*a*x,True))
        BMCplay31.Put("empezar",LoadBitmapSample(File.DirAssets,"empezar_410x150.png",Activity.Width*bb,Activity.Height*bb))

  ' Load all the list of maps  (60 but only between 5 and 30kb each one)
     
End If



    'using the bitmpas:
    fondo.Bitmap=BMCplay31.Get("blackfondo")
    fondo.DestRect.Initialize(0, 0, 100*x, 100*y)

 
    ' home button
    a=0.18
    ImageView1.SetBackgroundImage(BMCplay31.Get("menubutton"))
    ImageView1.Width=110*x*a
    ImageView1.Height=130*x*a 
    ImageView1.Top=ho
    ImageView1.Left=61*x

      ' more elements

 
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
 
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Yes, this layout contains imagenviews, and some of them are loaded directly in the designer and other by the code
 
Last edited:
Upvote 0

FJS

Active Member
Licensed User
Longtime User
Now all the bitmaps is loaded with its final size when I load them.
Now all the images loads its picture by means of bitmap cache only the first time (at activity create)

However, I have the following error during the first time (and it seems the list map can not to save more bitmaps, because there is not enough memory, no?):

B4X:
**
LogCat connected to: C2OKAS080865
--------- beginning of /dev/log/system


--------- beginning of /dev/log/main


** Service (wallpaperservice) Create **


** Service (wallpaperservice) Start **
** Service (wallpaperservice) Start **
** Service (wallpaperservice) Create **


** Service (wallpaperservice) Create **
** Service (wallpaperservice) Start **
** Service (wallpaperservice) Start **
** Activity (main) Create, isFirst = true **


** Activity (main) Resume **


** Activity (main) Pause, UserClosed = true **


** Activity (module_a) Create, isFirst = true **


** Activity (module_a) Resume **


** Activity (module_a) Pause, UserClosed = true **


** Activity (module_b) Create, isFirst = true **


** Activity (module_b) Resume **


received


** Activity (module_b) Pause, UserClosed = false **


** Activity (module_play) Create, isFirst = true **


** Activity (module_play) Resume **


received


** Activity (module_play) Pause, UserClosed = false **


** Activity (module_play3) Create, isFirst = true **


** Activity (module_play3) Resume **


** Activity (module_play3) Pause, UserClosed = false **


** Activity (game31) Create, isFirst = true **


java.lang.RuntimeException: LoadScaledBitmap: Out of memory.


    at flm.b4a.accelerview.ImageUtils.LoadScaledBitmap(ImageUtils.java:68)
    at b4a.brainsport_001.game31._activity_create(game31.java:593)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:173)
    at b4a.brainsport_001.game31.afterFirstLayout(game31.java:98)
    at b4a.brainsport_001.game31.access$100(game31.java:16)
    at b4a.brainsport_001.game31$WaitForLayout.run(game31.java:76)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4745)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)


    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)
java.lang.RuntimeException: LoadScaledBitmap: Out of memory.
** Activity (game31) Resume **



I reduced the quantity of the bitmaps, and I divided by two pack, I mean,first I load 40 elements like
B4X:
        a=0.15
        BMCplay31.Put("start",IU.LoadScaledBitmap(File.DirAssets,"start_410x150.png",410*x*a,150*x*a,True))
and 5seconds later, I load other 40 elements (and just in this moment the error message appears)

What can i do?, do you have any clue, please?

Do you think 80 elements are too many ( elements of list of map)? (not too weight, only between 3 to 40kb each one)
Do you recommend any other way to load 100 elements at the same time?
Do you think that 70 elements of gv.BitmapsData.Add(i) are too many?
Is necessary to add the following sentence?
B4X:
                    AcSf.Initialize("AcSf", True)
                    Activity.AddView(AcSf, 0, 0, 100%x, 100%y)

Thank you very much for your help, like always
 
Last edited:
Upvote 0

FJS

Active Member
Licensed User
Longtime User
ok Erel, thank you for your help, I am going to try it this evening.
However I have further comments:
1- the image sizes are the minimum, I use IU.LoadScaledBitmap with all the images to scale them just with its size
2- Is possible free the memory of the maps (and other objets), instantly?, for example in my case I have 3 minigames, when I open one of them, I would like free the memory of the list of map in the others.

Thank you very much
I hope my case will help to the rest of the forum
:)
 
Upvote 0
Top