Android Question Out of memory, expecially with maps

FrankBerra

Active Member
Licensed User
Longtime User
Hi all
My app is experiencing a lot of crashes on some devices due to out-of-memory error.
It is appearing sometimes ad especially when loading maps.
I can't deal with this out-of-memory error and i can't understand where and how to solve this problem.
My app opens some panels, and loads some images (about 10 images) with LoadBitMapSample. When i show also a map it crashes randomly e more frequently with errors like the following ones:

B4X:
I/dalvikvm-heap(28148): Clamp target GC heap from 66.376MB to 64.000MB
D/dalvikvm(28148): GC_FOR_ALLOC freed 84K, 11% free 58531K/65536K, paused 28ms, total 28ms
I/dalvikvm-heap(28148): Forcing collection of SoftReferences for 3240016-byte allocation
I/dalvikvm-heap(28148): Clamp target GC heap from 66.376MB to 64.000MB
D/dalvikvm(28148): GC_BEFORE_OOM freed 0K, 11% free 58531K/65536K, paused 35ms, total 35ms
E/dalvikvm-heap(28148): Out of memory on a 3240016-byte allocation.
I/dalvikvm(28148): "main" prio=5 tid=1 RUNNABLE
I/dalvikvm(28148):   | group="main" sCount=0 dsCount=0 obj=0x418ff5a8 self=0x401436a8
I/dalvikvm(28148):   | sysTid=28148 nice=0 sched=0/0 cgrp=apps handle=1075138556
I/dalvikvm(28148):   | state=R schedstat=( 19914758871 17748812518 35060 ) utm=1679 stm=311 core=3
I/dalvikvm(28148):   at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
I/dalvikvm(28148):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
I/dalvikvm(28148):   at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.InitializeSample(CanvasWrapper.java:550)
I/dalvikvm(28148):   at anywheresoftware.b4a.keywords.Common.LoadBitmapSample(Common.java:1172)
I/dalvikvm(28148):   at test.app.main._caricaprofiloutentetrovatodacache(main.java:2000)
I/dalvikvm(28148):   at test.app.main._visualizzaprofiloutentetrovatodacontatti(main.java:8084)
I/dalvikvm(28148):   at test.app.main._pannelliutentiinlista_touch(main.java:5658)
I/dalvikvm(28148):   at java.lang.reflect.Method.invokeNative(Native Method)
I/dalvikvm(28148):   at java.lang.reflect.Method.invoke(Method.java:525)
I/dalvikvm(28148):   at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
I/dalvikvm(28148):   at anywheresoftware.b4a.BA$1.run(BA.java:293)
I/dalvikvm(28148):   at android.os.Handler.handleCallback(Handler.java:730)
I/dalvikvm(28148):   at android.os.Handler.dispatchMessage(Handler.java:92)
I/dalvikvm(28148):   at android.os.Looper.loop(Looper.java:176)
I/dalvikvm(28148):   at android.app.ActivityThread.main(ActivityThread.java:5419)
I/dalvikvm(28148):   at java.lang.reflect.Method.invokeNative(Native Method)
I/dalvikvm(28148):   at java.lang.reflect.Method.invoke(Method.java:525)
I/dalvikvm(28148):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
I/dalvikvm(28148):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
I/dalvikvm(28148):   at dalvik.system.NativeStart.main(Native Method)
I/dalvikvm(28148): 
D/skia    (28148): --- decoder->decode returned false
I/dalvikvm-heap(28148): Clamp target GC heap from 66.357MB to 64.000MB
D/dalvikvm(28148): GC_EXPLICIT freed 20K, 11% free 58511K/65536K, paused 2ms+5ms, total 40ms
I/B4A     (28148): Downsampling image due to lack of memory: 2
I/Choreographer(28148): Skipped 186 frames!  The application may be doing too much work on its main thread.

My thoughts are: why my "simple" app crashes so frequently and others like Facebook, Google plus, Instagram etc. that are more heavy than mine doesn't crash at all?
Where I am failing in programming?
Anyone that suffered from the same problem can me point in the right direction?

Thanks!
 

eurojam

Well-Known Member
Licensed User
Longtime User
Some questions: What do you mean with "map" - I assume the collection structure? Do you store all your images into a map? Can you provide a code sample?
 
Upvote 0

An Schi

Well-Known Member
Licensed User
Noobish guess: your images are too big maybe?
You could try making them much smaller in (file)size and see if yor app runs then.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
that's 3Mb raw data. How many of those are there?

you can always convert those pictures to png if that library is the issue.
 
Last edited:
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
There are 7 images, all loaded with LoadBitmapSample.
Which vaule should i consider for ram occupation, the raw data of the original image as you said or the raw data of the BitmapSample?
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
you should count like width*height*4.

if the destination size is smaller than 900x900 then you need to count the destination sizes (*4) .
 
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
By the way the curious thing is that generally the app uses about 45mb of ram (info taken from Settings -> apps -> running apps) and whe i see it is downsampling images the app is still using about 45mb of ram.
So if the app doesn't eats more ram, why is it downsampling and then crashing whith out-of-memory errors? This is weird....
 
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
Just a clarification: what should i use as dimensions in LodaBitmapSample? image.Width or image.Width*1dip?
B4X:
LoadBitmapSample(File.DirInternalCache, "Photo.webp", image.Width, image.Height)
LoadBitmapSample(File.DirInternalCache, "Photo.webp", image.Width*1dip, image.Height*1dip)
Are there some noticable benefits between the two versions?
 
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
I investigated into the code of the program and analyzed the consumption of ram.
Probably i found the problem: while i am loading real images/photos i also load some icons into a menu. These icons in the menu are loaded from the designer which lacks an option to load a bitmap like LoadBitmapSample.
So i suggest you to add an option in the future versions of B4A to load the images from the designer as you load it programmatically whith LoadBitmapSample.
I tryed to load these icons programmatically with LoadBitmapSample and the ram consumption has been reduced a bit.

I also read around on the documentation on Android Developers that the OS frees resurces of the app only if they aren't used anymore; if a resource is declared globally (as i am doing because i need to change the images programmatically for example) can't be freed automatically instantly (it will be freed only after a while after the app is closed)
Now i want to try to free resurces manually, for example can i load the images into maps collections (not google maps) and clear the map on exit (or when i remove the panel containing the images) like the following example?

EXAMPLE 1
B4X:
Sub Globals
   Dim ImagesMap as Map
   Dim Image1 as imageview
   Dim Image2 as Imageview
End sub

Sub Activity_Create(FirstTime as Boolean)
   ImagesMap.Initialize
   ImagesMap.Put("Photo1", LoadBitmapSample(File.DirInternalCache, "Photo1.webp", image1.Width, image1.Height))
   ImagesMap.Put("Photo2", LoadBitmapSample(File.DirInternalCache, "Photo2.webp", image2.Width, image2.Height))

   Image1.Bitmap = ImagesMap.get("Photo1")
   Image2.Bitmap = ImagesMap.get("Photo2")
End Sub

Sub Activity_Pause (UserClosed as boolean)
  If UserClosed == true then
      ImagesMap.Clear 'I clear the map holding the images
  End If
End sub

Or simply load a 1x1px image on exit (or when i close a panel holding the images that i don't need anymore)?
EXAMPLE 2
B4X:
Sub Globals
   Dim Image1 as imageview
   Dim Image2 as Imageview
End sub

Sub Activity_Create(FirstTime as Boolean)
   Image1.Bitmap = LoadBitmapSample(File.DirInternalCache, "Photo1.webp", image1.Width, image1.Height)
   Image2.Bitmap = LoadBitmapSample(File.DirInternalCache, "Photo2.webp", image2.Width, image2.Height)
End Sub

Sub Activity_Pause (UserClosed as boolean)
  If UserClosed == true then
      Image1.Bitmap = LoadBitmapSample(File.DirInternalCache, "Photo1.webp", 1, 1) 'I load images 1x1px for reducing ram consumption
      Image2.Bitmap = LoadBitmapSample(File.DirInternalCache, "Photo2.webp", 1, 1) 'I load images 1x1px for reducing ram consumption
  End If
End sub

Do you think in this way i can free resurces manually?
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
I think the map only contains a reference to the other global imageview so the clearing just removes the reference and not the imageview.

Edit: sorry, you didn't add the imageview object so the above is wrong :)

loading a 1x1 pixel image is an idea but the app gets closed anyway so these get removed automatically I guess?

you can also add the images to a panel and use panel.removeallviews.
 
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
I tried a lot:
1) entering into app and then looking into android settins for ram consumption
2) entering into app, opening the panel holding the images, then close the panel and fireing the panel with panel.removeallviews and then looking into android settins for ram consumption.

After Second test if the resurces are really released i suppose to obtain a ram consumption similar to First test. That doesn't happen and the ram consumption is higher than first test, so i guess that panel.removeallviews doesn't free resurces of ImagesViews that are still declared globally (but not anymore displayed)
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
so when you work with images that are also put into an array or map you need to use removeallview & map clean?

can you put null into the imageviews array to get rid of the reference?
 
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
I experimented the following instructions all placed in Sub Activity_Pause:
B4X:
Image1.Bitmap = Null
Image1 = Null
Image1.Bitmap = LoadBitmapSample(File.DirInternalCache, "Photo1.webp", 1, 1)
'and also
Activity.RemoveAllViews

When the services play alone in background the app consumes about 6Mb of ram, when i open the app the used ram rises about 15Mb and if i play around also opening google maps inside the app the used ram rises about 45Mb.
I am expecting that if I call Image1 = Null (or LoadBitmapSample(.. ,1,1)) the graphic resources are freed and the memory consumption falls down.

Why it doesn't happen? I started to feel frustrated...
 
Last edited:
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
After loading ALL images with LoadBitmapSample (and forcing a larger heap) i don't get out-of-memory errors anymore but i try to investigate the ram consumption. Now the app is in early stage of development so i feel afraid about what can happen in the future if the app grows up so i want to understand how to handle the ram consumption.
Should i worry about?

If i close a panel (but not the app) holding images should i "Nullify" the imageViews to free resources?
 
Upvote 0
Top