Android Question convert CustomListView to CustomListView with lazy loading with data from httpjob

Schakalaka

Active Member
Licensed User
Longtime User
Hello,
I use this code, for create a customlistview from httpjob

B4X:
Sub downloadEmailsLista
    
    UsersCV.Clear
    Dim bytemail() As Byte
    Dim byteSalsy() As Byte

    Dim index As Int = 1

    e.Initialize
    Dim j As HttpJob
    j.Initialize("", Me) 'name is empty as it is no longer needed
    j.Download(ServerURl & "/xxxxxxxxxxxxxx/restapi.php?api=tbl-users&orderby=my_iduser&sort=asc") '&orderby=my_iduser&sort=asc") '2")
    ProgressDialogShow2("Loading User list...",False)
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Log(j.GetString)

        Dim parser As JSONParser
        parser.Initialize(j.getstring)
        Dim jRoot As List = parser.NextArray
        For Each coljRoot As Map In jRoot
            my_enabled = coljRoot.Get("my_enabled")
            my_appversion = coljRoot.Get("my_appversion")
            my_email = coljRoot.Get("my_email")
            my_last_see = coljRoot.Get("my_last_see")
            my_btcaddress = coljRoot.Get("my_btcaddress")
            my_ispremium = coljRoot.Get("my_ispremium")
            Dim my_salt As String = coljRoot.Get("my_salt")
            Dim my_registration_date As String = coljRoot.Get("my_registration_date")
            Dim my_iduser As Int = coljRoot.Get("my_iduser")
            
            byteSalsy = encode.DecodeBase64(my_salt)

            Dim stringSalt As String = DecryptText(byteSalsy,Main.app_id)

            my_salt = stringSalt

            bytemail = encode.DecodeBase64(my_email)
    
            stringmail = DecryptText(bytemail,my_salt)
            e.Add(stringmail)
    
            DateTime.DateFormat = "yyyy-MM-dd HH:mm:ss"
            Dim dt As Long = DateTime.DateParse(my_last_see)
            DateTime.DateFormat = "dd/MM/yyyy"
'            Log(DateUtils.PeriodBetweenInDays(DateTime.DateParse($"$Date{dt}"$),DateTime.Now).Days)
        
            Dim daydif As Int = DateUtils.PeriodBetweenInDays(DateTime.DateParse($"$Date{dt}"$),DateTime.Now).Days
       
            UsersCV.Add(CreateItem(UsersCV.AsView.Width, my_iduser, stringmail, daydif,my_appversion), "")

        
        Next

    

    Else
        ToastMessageShow("Error: " & j.ErrorMessage, True)
    End If
    j.Release

    ProgressDialogHide
End Sub

This is for create the Item

B4X:
Private Sub CreateItem(Width As Int, userid As String, email As String, last As String, version As String) As Panel
    Dim p As B4XView = xui.CreatePanel("")
    Dim height As Int = 160dip 'UsersCV.AsView.Height '350dip  '50dip
    p.SetLayoutAnimated(0, 0, 0, Width, height)
    p.LoadLayout("CLV_UTENTI")
    p.Color = Colors.Cyan
    
    If my_enabled = 0 Then 
        Panel1.Color = 0xAEFF0000
    End If
    lbluserID.Text = userid 'user id da searchbox
    lblemail.Text = email 'email decriptata
        
    lbllastactivity.Text = "Ultima attività: "
    txtastactivity.Text = last 'differenza in giorni della ultima attività
    
    lblversion.Text = "Versione: "
    txtversion.Text = version
    index = userid
    Return p

End Sub


I would like to convert it into CustomListView with lazy loading and then, on click event, log the value of lbluserID.Text instead the INDEX.

In some exaples that I found here, the date doesn't come from a httpjob and I don't know how to do it

Thank you
 

Quandalle

Member
Licensed User
In your case the data does not come directly from an HTTP job but from a list called jRoot.
You have to make this list persist outside your sub downloadEmailsLista by declaring the jRoot variable not local to the sub downloadEmailsLista but global to your module
You can then remove all the decoding at this place and put it in a sub decodeLine (index) which decodes a line of your jRoot structure. The line is obtained by jRoot.Get(index)

This allows to integrate in lazzyloading calls that use FirstIndex, LstIndex ranges

B4X:
sub globals
    dim jRoot as list
    ...
end sub

Sub downloadEmailsLista
....
..
    If j.Success Then
        Log(j.GetString)
        Dim parser As JSONParser
        parser.Initialize(j.getstring)
       jRoot  = parser.NextArray
    Else
        ToastMessageShow("Error: " & j.ErrorMessage, True)
    End If
    j.Release

    ProgressDialogHide
End Sub

B4X:
sub decodeline(index)
            dim coljRoot as map
            coljRoot = jRoot.get(index)
            my_enabled = coljRoot.Get("my_enabled")
            my_appversion = coljRoot.Get("my_appversion")
            my_email = coljRoot.Get("my_email")
            my_last_see = coljRoot.Get("my_last_see")
....
...
end sub
 
Upvote 0

Schakalaka

Active Member
Licensed User
Longtime User
In your case the data does not come directly from an HTTP job but from a list called jRoot.
You have to make this list persist outside your sub downloadEmailsLista by declaring the jRoot variable not local to the sub downloadEmailsLista but global to your module
You can then remove all the decoding at this place and put it in a sub decodeLine (index) which decodes a line of your jRoot structure. The line is obtained by jRoot.Get(index)

This allows to integrate in lazzyloading calls that use FirstIndex, LstIndex ranges

B4X:
sub globals
    dim jRoot as list
    ...
end sub

Sub downloadEmailsLista
....
..
    If j.Success Then
        Log(j.GetString)
        Dim parser As JSONParser
        parser.Initialize(j.getstring)
       jRoot  = parser.NextArray
    Else
        ToastMessageShow("Error: " & j.ErrorMessage, True)
    End If
    j.Release

    ProgressDialogHide
End Sub

B4X:
sub decodeline(index)
            dim coljRoot as map
            coljRoot = jRoot.get(index)
            my_enabled = coljRoot.Get("my_enabled")
            my_appversion = coljRoot.Get("my_appversion")
            my_email = coljRoot.Get("my_email")
            my_last_see = coljRoot.Get("my_last_see")
....
...
end sub
hello,
after some month i'm back on this project..

I have create a demo, but I have lost something in your instruction....
I dont understasnd how to setup the laz", and of course, when remove the for each circle inside the job, nothing works,,
 

Attachments

  • customhttplazy.zip
    12.2 KB · Views: 154
Upvote 0

Schakalaka

Active Member
Licensed User
Longtime User
In your case the data does not come directly from an HTTP job but from a list called jRoot.
You have to make this list persist outside your sub downloadEmailsLista by declaring the jRoot variable not local to the sub downloadEmailsLista but global to your module
You can then remove all the decoding at this place and put it in a sub decodeLine (index) which decodes a line of your jRoot structure. The line is obtained by jRoot.Get(index)

This allows to integrate in lazzyloading calls that use FirstIndex, LstIndex ranges

B4X:
sub globals
    dim jRoot as list
    ...
end sub

Sub downloadEmailsLista
....
..
    If j.Success Then
        Log(j.GetString)
        Dim parser As JSONParser
        parser.Initialize(j.getstring)
       jRoot  = parser.NextArray
    Else
        ToastMessageShow("Error: " & j.ErrorMessage, True)
    End If
    j.Release

    ProgressDialogHide
End Sub

B4X:
sub decodeline(index)
            dim coljRoot as map
            coljRoot = jRoot.get(index)
            my_enabled = coljRoot.Get("my_enabled")
            my_appversion = coljRoot.Get("my_appversion")
            my_email = coljRoot.Get("my_email")
            my_last_see = coljRoot.Get("my_last_see")
....
...
end sub

Hello,
i have try many times also with chatgpt to generatea working code but nothing works.
The last is this:



B4X:
Sub downloadEmailsLista
    ' Initialize the variables.
    Dim UsersCV As CustomListView
    Dim bytemail() As Byte
    Dim byteSalsy() As Byte
    Dim index As Int = 1
    Dim e As List
    e.Initialize
    ' Create the custom list view.


    ' Load the data from the API.
    Dim j As HttpJob
    j.Initialize("", Me) 'name is empty as it is no longer needed
    j.Download(ServerURl & "/clickandclaim-host/restapi.php?api=tbl-users&orderby=my_iduser&sort=asc")
    ProgressDialogShow2("Loading User list...",False)
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Log(j.GetString)

        Dim parser As JSONParser
        parser.Initialize(j.getstring)
        jRoot  = parser.NextArray
    Else
        ToastMessageShow("Error: " & j.ErrorMessage, True)
    End If
    j.Release

    ProgressDialogHide


End Sub


B4X:
Sub JobDone(j As HttpJob)
    If j.Success Then
        Log(j.GetString)

        Dim parser As JSONParser
        parser.Initialize(j.getstring)
        jRoot  = parser.NextArray
    Else
        ToastMessageShow("Error: " & j.ErrorMessage, True)
    End If
    j.Release

    ProgressDialogHide
End Sub

B4X:
Private Sub UsersCV_LazyLoad (FirstIndex As Int, LastIndex As Int)
    Dim bytemail() As Byte
    Dim byteSalsy() As Byte
    Dim daydif As Int = 0

    Dim ExtraSize As Int = 20

    For i As Int = Max(0, FirstIndex - ExtraSize) To Min(LastIndex + ExtraSize, UsersCV.Size - 1):
        If i >= jRoot.Size Then Exit

        Dim coljRoot As Map = jRoot.Get(i)
        my_enabled = coljRoot.Get("my_enabled")
        my_appversion = coljRoot.Get("my_appversion")
        my_email = coljRoot.Get("my_email")
        my_last_see = coljRoot.Get("my_last_see")
        my_iduser = coljRoot.Get("my_iduser")

        UsersCV.Add(CreateItem(UsersCV.AsView.Width, my_iduser, my_email, daydif, my_appversion), "")
    Next
  
End Sub

here return "waiting for regular variable followed with "="


B4X:
Private Sub CreateItem(Width As Int, userid As String, email As String, last As String, version As String) As Panel
    Dim p As B4XView = xui.CreatePanel("")
    Dim height As Int = 160dip 'UsersCV.AsView.Height '350dip  '50dip
    p.SetLayoutAnimated(0, 0, 0, Width, height)
    p.LoadLayout("CLV_UTENTI")
    p.Color = Colors.Cyan

    lbluserID.Text = userid
    lblemail.Text = email

    lbllastactivity.Text = "Ultima attività: "
    txtastactivity.Text = last

    lblversion.Text = "Versione: "
    txtversion.Text = version
    index = userid
    Return p
End Sub

B4X:
Sub UsersCV_VisibleRangeChanged(FirstVisible As Int, LastVisible As Int)
    ' Lazy load the data for the visible range
    Dim Items() As Object
    Items = LoadData(FirstVisible, LastVisible)
    ' Add the items to the custom list view.
    For i = FirstVisible To LastVisible
        UsersCV.Add(Items(i), "")
    Next
End Sub

B4X:
Sub LoadData(FirstVisible As Int, LastVisible As Int) As Object()
    ' Create an array to store the data
    Dim Items() As Object
    ' Iterate over the visible range
    For i = FirstVisible To LastVisible
        ' Add the data to the array
        Items = Array(i)
    Next
    ' Return the array
    Return Items
End Sub

alternative of coe
B4X:
Sub UsersCV_LazyLoad(FirstIndex As Int, LastIndex As Int)

Dim ExtraSize As Int = 20
Dim daydif As Int
Dim items() As Object

If jRoot.IsInitialized Then
    items = jRoot.GetRange(FirstIndex, LastIndex + 1)
    For i As Int = 0 To items.Size - 1
        daydif = DateUtils.GetDaysBetween(DateTime.Now, items(i).Get("my_last_see"))
        UsersCV.Add(CreateItem(UsersCV.AsView.Width, items(i).Get("my_iduser"), items(i).Get("my_email"), daydif, items(i).Get("my_appversion")), "")
    Next
End If

End Sub
{/code]
This rewrite uses another technique to rewrite the For loop. Instead of iterating directly on the jRoot array, the function creates a new array items that contains only the elements of the jRoot array that are located within the specified range. This makes the code more efficient, since it is not necessary to iterate over the entire jRoot array each time the method is called.

I can upload a demo for test the code
 
Last edited:
Upvote 0
Top