Android Question Imagedownoader taking up to 110mb of memory

Sub7

Active Member
Licensed User
Longtime User
Hello, i am using part of this code to populate a customlistview and download a list of images which the dimensions of the downloaded images are maximum 100x100px and the size is maximum size is 10kb, most of them are 4kb.
The images show in the customlistview are only 60x60dip.
If i download only 20/30 images the memory usage drop to 40mb + - (which is still alot)
with 100/150 images the memory used it about 110mb and up!

I tried to fix but no success, any hint please?

Thanks

Here the code code:
B4X:
#Region  Service Attributes
    #StartAtBoot: False
#End Region

Sub Process_Globals
    Private cache As Map
    Private tasks As Map
    Private ongoingTasks As Map
End Sub

Sub Service_Create
    tasks.Initialize
    cache.Initialize
    ongoingTasks.Initialize
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub

Sub Service_Destroy

End Sub

Sub Download (ImageViewsMap As Map)
    For i = 0 To ImageViewsMap.Size - 1
        tasks.Put(ImageViewsMap.GetKeyAt(i), ImageViewsMap.GetValueAt(i))
        Dim link As String = ImageViewsMap.GetValueAt(i)
        If cache.ContainsKey(link) Then
            Dim iv As ImageView = ImageViewsMap.GetKeyAt(i)
            iv.SetBackgroundImage(cache.Get(link))
            Else If ongoingTasks.ContainsKey(link) = False Then
            ongoingTasks.Put(link, "")
            Dim j As HttpJob
            j.Initialize(link, Me)
            j.Download(link)
        End If
    Next
End Sub


Sub JobDone(Job As HttpJob)
    ongoingTasks.Remove(Job.JobName)
    If Job.Success Then
        Dim bmp As Bitmap = Job.GetBitmap
        Log(Job.GetBitmap)
        cache.Put(Job.JobName, bmp)
        Log(cache.Put(Job.JobName, bmp))
        If tasks.IsInitialized Then
            For i = 0 To tasks.Size - 1
         
                Dim link As String = tasks.GetValueAt(i)
                If link = Job.JobName Then
                    Dim iv As ImageView = tasks.GetKeyAt(i)
                    iv.SetBackgroundImage(bmp)
                    If ongoingTasks.Size=0 Then StopService("imagedownloader2")
                End If
            Next   
        End If
    Else
        Log("Error downloading image: " & Job.JobName & CRLF & Job.ErrorMessage)
    End If
    Job.Release
End Sub

Sub ActivityIsPaused
    tasks.Clear
End Sub

Public Sub ClearCache
    cache.Clear
    Log("clean")
End Sub
 

Sub7

Active Member
Licensed User
Longtime User
Are you sure that the images size is only 100x100? The file size is not important. Only the image size.

You can use LoadBitmapSample instead of LoadBitmap to reduce the image size (you will need to download HttpUtils2 source code).

Hello Erel, i checked that, the images are 160x160 and not 100x100, size: 4-5kb (all images are very optimized for web).
I will try with other code but this one was handy, works nice, just takes way too much memory.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Looking at the code briefly, it seems to me that two map contain bitmaps.

Even assuming that both contain:

"If i download only 20/30 images the memory usage drop to 40mb..."
...
the images are 160x160 and not 100x100, size: 4-5kb

if the images have a size of 5kb:

30 x 5Kb x 2 = 300Kb... how can it be 40Mb?
 
Upvote 0

Sub7

Active Member
Licensed User
Longtime User
Looking at the code briefly, it seems to me that two map contain bitmaps.

Even assuming that both contain:

"If i download only 20/30 images the memory usage drop to 40mb..."
...
the images are 160x160 and not 100x100, size: 4-5kb

if the images have a size of 5kb:

30 x 5Kb x 2 = 300Kb... how can it be 40Mb?

Hi, dunno, im here asking to understand :D
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
An image with a size of 160*160 will need approx 100kb of memory
160*160*4 (32bit->4byte each pixel) = 102.400 bytes
Maybe more; i dont know exactly how many ram an loaded image will eat.

as Erel already stated: the filesize does NOT matter. The Image-dimensions DOES matter.
 
Upvote 0

Sub7

Active Member
Licensed User
Longtime User
Thank you! so my app is taking memory somewhere else.
I do not get Out of memory errors but i see is taking alot of memory for doing almost nothing, facebook takes the same ram amount (and my app is basically a customlistview with some text and images downloaded from internet)
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Are you getting an out of memory error? If not then it is possible that the garbage collector is waiting for more allocations before it releases the memory.

Though as @DonManfred and myself tried to explain, the file size doesn't matter. Only the image size. 100+ images can take a lot of memory.

You can use a UltimateListView instead which removes and adds images dynamically.
 
Upvote 0

Sub7

Active Member
Licensed User
Longtime User
Hi Erel, i dont get out of memory errors, i just see that with it takes way too much memory to render 100/300 rows.
I never see the memory dropping, even when the app has finished to load all the images (which takes about 10 seconds)
Is the anyway to catch which part of the code is taking that much memory?
My customlistview has 2 lables and 1 image 60x60dip and for each row i change text colors according with it's content (richstring).
Ill post my code sap.
 
Upvote 0

Sub7

Active Member
Licensed User
Longtime User
Here is part of my dirty code that use imagedownloader, i dont have any warning but for sure i have some programming mistake (errorlog are not showing anything)
For each row, i am calling get_img to download the single image, from what i can see form the logs the images are downloaded immediately but they take some time to show on the imageview in p.LoadLayout("clvlayout")


B4X:
Sub get_img
Dim links As Map
    links.Initialize
    links.Put(image, url)
    CallSubDelayed2(ImageDownloader2, "Download", links)
End Sub


Sub fill
Dim parser As JSONParser
        parser.Initialize(srvanswer)
                Dim arr As List
                arr = parser.NextArray
                For i = 0 To arr.Size - 1
                    Dim m As Map
                    m = arr.get(i)
                    'Log(srvanswer)
                    id = m.get("ID")
                    field1 = m.get("field1")
                    field2 = m.get("field2")
                    field3 = m.get("field3")
                    field4 = m.get("field4")
                    field5 = m.get("field5")
                    field6 = m.get("field6")
                    typef = m.get("type")
               
                'Manage type
                If typef == 1  Then
                header.Initialize("{Blue}" &field2&"{Blue}" & " " &"{White}"&field3&"{White}" )
                header.Color2(Colors.White,"{White}")
                header.Color2(Colors.RGB(52,181,246),"{Blue}")
                header.Style2(header.STYLE_BOLD, "{B}" )
                Else If typef == 2  Then
                fiel1.ToUpperCase
                header.Initialize("{Green}" &field2& "{Green}" & " " &"{White}"&field3&"{White}" )
                header.Color2(Colors.White,"{White}")
                header.Color2(Colors.Green,"{Green}")
                header.Style2(header.STYLE_BOLD, "{B}" )r
                End If

                    entry.Initialize("{White}{B}Details:{B} " & field4 & " " & field5 & " More: "&CRLF& field6 &"{White}")
                    entry.Color2(Colors.white, "{White}")
                    entry.Style2(header.STYLE_BOLD, "{B}" )
                    Dim p As Panel
                    p.Initialize("")
                    p.Color = Colors.ARGB(255,28,28,28)
                    listview1.Add(p, 90dip, field1&"#"&id)
                    p.LoadLayout("clvlayout")
                    Label1.Color = Colors.RGB("28","28","28")
                    Label2.Color = Colors.RGB("28","28","28")
                    Label1.Text = header
                    Label2.Text = entry
                    'Get device size and change text size
                    If lv.ApproximateScreenSize < 3 Then
                    Label1.TextSize = 12
                    Label2.TextSize = 12
                    Else If lv.ApproximateScreenSize > 3 AND lv.ApproximateScreenSize < 6 Then
                    Label1.TextSize = 13
                    Label2.TextSize = 13
                    Else If lv.ApproximateScreenSize > 6  AND lv.ApproximateScreenSize < 9 Then
                    Label1.TextSize = 17
                    Label2.TextSize = 17
                    Else If lv.ApproximateScreenSize > 9 Then
                    Label1.TextSize = 19
                    Label2.TextSize = 19
                    End If
           
                    'Call imagedownloader sub
                    get_img
               
                    'Small icon near the first label.
                    If is_on == 1 Then
                    rating_on.SetBackgroundImage(LoadBitmapSample(File.DirAssets, "is_on.png", 15,15))
                    Else
                    rating_off.SetBackgroundImage(LoadBitmapSample(File.DirAssets, "is_off.png",15,15))
                    End If

                Next
        End If
                ProgressDialogHide
                'CallSub(ImageDownloader2, "ClearCache")
End Sub

Service module:

B4X:
#Region  Service Attributes
    #StartAtBoot: False
#End Region

Sub Process_Globals
    'Private cache As Map
    Private tasks As Map
    Private ongoingTasks As Map
End Sub

Sub Service_Create
    tasks.Initialize
    'cache.Initialize
    ongoingTasks.Initialize
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub

Sub Service_Destroy

End Sub


Sub Download (ImageViewsMap As Map)
    For i = 0 To ImageViewsMap.Size - 1
        tasks.Put(ImageViewsMap.GetKeyAt(i), ImageViewsMap.GetValueAt(i))
        Dim link As String = ImageViewsMap.GetValueAt(i)
            ongoingTasks.Put(link, "")
            Dim j As HttpJob
            j.Initialize(link, Me)
            j.Download(link)
    Next
End Sub


Sub JobDone(Job As HttpJob)
    ongoingTasks.Remove(Job.JobName)
    If Job.Success Then
        Dim bmp As Bitmap = Job.GetBitmap
        If tasks.IsInitialized Then
            For i = 0 To tasks.Size - 1
                Dim link As String = tasks.GetValueAt(i)
                If link = Job.JobName Then
                    Dim iv As ImageView = tasks.GetKeyAt(i)
                    iv.SetBackgroundImage(bmp)
                    If ongoingTasks.Size=0 Then StopService("imagedownloader2")
                End If
       
            Next
           
        End If
    Else
        Log("Error downloading image: " & Job.JobName & CRLF & Job.ErrorMessage)
    End If
    Job.Release

End Sub

Sub ActivityIsPaused
    tasks.Clear
End Sub

Thank you
 
Upvote 0
Top