Android Question CustomListView With Lazy Loading question

CR95

Active Member
Licensed User
In a "standard" CLV with LL application, I notice that the subroutine "clv1_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)" is launched as many times as the number of lines of the "visible" CLV.
For example, for a CLV counting 4 visible items, the subroutine is launched 3 times with :
- FirstIndex= 0 LastIndex= 1
- FirstIndex= 0 LastIndex= 2
- FirstIndex= 0 LastIndex= 3

This is not really an issue but, in my case, for each item, I am loading pictures from an external site and the transfer of these images is relatively long.

My question is : is there a way to avoid these multiple "identical" passes ans consequently these multiple transferts ?
 

Alexander Stolte

Expert
Licensed User
Longtime User
My question is : is there a way to avoid these multiple "identical" passes ans consequently these multiple transferts ?
The lazy loading only reloads the items that are in the visible area and do not yet have a layout.
As none of us here know your code, we can only help to a limited extent. But here are a few things you can do if you haven't already done so:
  • Cache the images - Download them once and then save them temporarily, then it doesn't matter how often they are loaded
  • Make the loading of the images asynchronous, so that the remaining items are added and the lazy loading recognizes that a layout has already been loaded there
 
Upvote 0

CR95

Active Member
Licensed User
Thanks Alexander
As none of us here know your code
My table AllPictures (size = ReadSize) contains all the names of the pictures to load
B4X:
'---Construction de la CLV
    For i = 0 To ((ReadSize/3) -1)
        Dim id1 As String = AllPictures.Get(i*3)
        Dim id2 As String = AllPictures.Get((i*3)+1)
        Dim id3 As String = AllPictures.Get((i*3)+2)
        Dim p As B4XView = CreateItem(Rnd(100dip, 300dip) + 60dip)
        ' Add item in CLV and Value contains Array
        CLV1.Add(p, Array As String (id1, id2, id3))
    Next
item2 layout contains 3 ImageViews on the same line
B4X:
'    Item Creation with Expanded Height
Sub CreateItem(ExpandedHeight As Int) As B4XView
    Dim p As B4XView = xui.CreatePanel("")
    p.SetLayoutAnimated(0, 0, 0, CLV1.AsView.Width, ExpandedHeight)
    p.LoadLayout("Item2")
    p.SetLayoutAnimated(0, 0, 0, p.Width, ItemHeight) 'resize it to the collapsed height
    Return p
End Sub

B4X:
Sub CLV1_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)
    Log("Appel de CustomListView FirstIndex= " & FirstIndex & " Last= " & LastIndex)
    For i = 0 To CLV1.Size - 1
        Dim item As CLVItem = CLV1.GetRawListItem(i)
        Dim pnl As B4XView = xui.CreatePanel("")
        Log("i= " & i)
        If i >= FirstIndex And i <= LastIndex Then
            item.Panel.AddView(pnl, 0, 0, item.Panel.Width, item.Panel.Height)
            Dim data() As String = item.Value
            'Create the item layout
            pnl.LoadLayout("item2")
            For x = 0 To 2
                Log("Index=" & data(x))
                DownloadAndSetImage("http://" & IPAddress & DiskAd & data(x) & "/", pnl.GetView(0).GetView(x))   
            Next
        Else    ' Not visible
            pnl.RemoveAllViews
        End If
B4X:
Sub DownloadAndSetImage(Url As String, ImageView As B4XView)
    Log("Download=" & Url)
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download(Url)
    Wait For (j) JobDone (j As HttpJob)
    If j.Success Then
        Try
            If ImageView.Parent.Parent.IsInitialized Then
                Dim bmp As B4XBitmap = j.GetBitmapResize(ImageView.Width, ImageView.Height, True)
                ImageView.SetBitmap(bmp)
            End If
        Catch
            Log(LastException)
        End Try
    End If
    j.Release
End Sub

The lazy loading only reloads the items that are in the visible area and do not yet have a layout.
My Log does not show this "only reloads"
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
My Log does not show this "only reloads"
Check the Tutorial about Lazy Loading to get a better insight of this feature

 
Upvote 0

Alexander Stolte

Expert
Licensed User
Longtime User
If i >= FirstIndex And i <= LastIndex Then
Something crucial is missing here.

you need to check this:
B4X:
If p.NumberOfViews = 0 Then
this is very important for the performance.

This is the right code for lazyloading:
B4X:
Sub CLV1_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)
   Dim ExtraSize As Int = 20
   For i = 0 To CLV1.Size - 1
       Dim p As B4XView = CLV1.GetPanel(i)
       If i > FirstIndex - ExtraSize And i < LastIndex + ExtraSize Then
           'visible+
           If p.NumberOfViews = 0 Then
               Dim cd As CardData = CLV1.GetValue(i)
               p.LoadLayout("Card1")
               lblTitle.Text = cd.Title
               lblContent.Text = cd.Content
               SetColorStateList(lblAction1, xui.Color_LightGray, lblAction1.TextColor)
               SetColorStateList(lblAction2, xui.Color_LightGray, lblAction2.TextColor)
               ImageView1.SetBitmap(xui.LoadBitmapResize(File.DirAssets, cd.BitmapFile, ImageView1.Width, ImageView1.Height, True))
               UpdateItemColor(i, cd.Color) '<-------------
           End If
       Else
           'not visible
           If p.NumberOfViews > 0 Then
               p.RemoveAllViews
           End If
       End If
   Next
End Sub
source: https://www.b4x.com/android/forum/threads/b4x-xui-customlistview-lazy-loading-virtualization.87930/
 
Upvote 0
Top