Android Question xCLV with AutoTextSizeLabels and Checkboxes

Mahares

Expert
Licensed User
Longtime User
I have an xCLV with an AutoTextSizeLabel, a series of buttons and a series of CheckBoxes. The data is populated from a small SQLite database table with 200 records.
I select a few items by clicking a number of checkboxes. Then, I click a button below the xCLV that displays all items that were checked in the checkboxes. It returns the following error. However, if I use only 35 records in the SQL statement with LIMIT 35 instead of LIMIT 200, there is no crash. I am including a small project that reproduces the behavior. Thank you.
The relevant button code is:
B4X:
Sub btn_Click
    Dim checkedItems As List
    checkedItems.Initialize
    For i = 0 To clv2.size - 1
        Dim p As B4XView = clv2.GetPanel(i)
        Dim chk As B4XView = p.GetView(1)  'this is line 88 crash
        If chk.Checked Then
            checkedItems.Add(clv2.GetValue(i))
        End If
    Next
    Log($"${checkedItems.Size} Checked items:${checkedItems}"$)
End Sub
B4X:
** Activity (main) Resume **
Error occurred on line: 88 (Main)
java.lang.RuntimeException: Object should first be initialized (View).
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
at anywheresoftware.b4a.objects.B4XViewWrapper.GetView(B4XViewWrapper.java:317)
at b4a.example.main._btn_click(main.java:646)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
at android.view.View.performClick(View.java:6300)
at android.view.View$PerformClick.run(View.java:24941)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
** Activity (main) Pause, UserClosed = true **
** Service (starter) Destroy (ignored)**
 

Attachments

  • xClvAutoTextSizeLabelChkBoxForForum.zip
    16 KB · Views: 125

Erel

B4X founder
Staff member
Licensed User
Longtime User
Why use Android 2 theme??? Looks old and will cause problems.
Use instead:
B4X:
CreateResourceFromFile(Macro, Themes.LightTheme)

You are not implementing lazy loading correctly.
The whole point of lazy loading is that only the layouts of the visible items are created. This means that:
1. You cannot access the views of non-visible items.
2. You shouldn't rely on the views state to store the app state. This is explained here: https://www.b4x.com/android/forum/t...ew-lazy-loading-virtualization.87930/#content
 
Upvote 0

Hamied Abou Hulaikah

Well-Known Member
Licensed User
Longtime User
Try change btn_Click event to this:
B4X:
Sub btn_Click
    Dim checkedItems As List
    checkedItems.Initialize
    For i = 0 To clv2.size - 1
        Dim p As B4XView = clv2.GetPanel(i)
        For Each chk As B4XView In p.GetAllViewsRecursive
            If chk Is CheckBox Then
                If chk.Checked Then
                    checkedItems.Add(clv2.GetValue(i))
                End If
            End If
        Next
    Next
    Log($"${checkedItems.Size} Checked items:${checkedItems}"$)   
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Try change btn_Click event to this:
Replacing my sub with yours worked well. Thank you.
Can someone see where the lazy loading in the below sub is a problem in my code as Erel alluded to. I cannot see it. I seem to have an easier time solving other people problems than mine.
B4X:
Sub clv2_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)    
    Dim ExtraSize As Int = 20 '
    For i = Max(0, FirstIndex - ExtraSize) To Min(LastIndex + ExtraSize, clv2.Size - 1) 'Loop for adding/removing your items layout to or from the list
        Dim Pnl As B4XView = clv2.GetPanel(i) 
        If i > FirstIndex - ExtraSize And i < LastIndex + ExtraSize Then 'Add a new item to the list
            If Pnl.NumberOfViews = 0 Then '
                Dim TD As TestData = clv2.GetValue(i) 
                Pnl.LoadLayout("CellItem") 
                Label1.Text = TD.LabelText                
                Button1.SetColorAndBorder(xui.Color_LightGray,2dip,Colors.Cyan,5dip)
                CheckBox1.Color=xui.Color_White  
            End If
        Else 
            If Pnl.NumberOfViews > 0 Then
                Pnl.RemoveAllViews 'Remove none visible item from the main xCLV layout
            End If
        End If    
    Next
End Sub
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Could someone please tell why this code to iterate through all the clicked checkboxes using the button at the bottom of the screen, still crashes with the same error as pointed out in post #1, despite making changes offered in the previous posts. I tried to get some pointers from the links given and others that have similar snippets, but no success. I have updated the project and I am attaching the newer one here, .
B4X:
Sub btn_Click
    Dim checkedItems As List
    checkedItems.Initialize
    For i = 0 To clv2.size - 1
        Dim p As B4XView = clv2.GetPanel(i)
        Dim chk As B4XView = p.GetView(1)  'Crash big time
        If chk.Checked Then
            Dim td As TestData =clv2.GetValue(i)
            checkedItems.Add(td.LabelText)
        End If
    Next
    Log($"${checkedItems.Size} Checked items:${checkedItems}"$)  
End Sub
 

Attachments

  • xClvAutoTextSizeLabelChkBoxSecondTry.zip
    16.5 KB · Views: 103
Upvote 0

toby

Well-Known Member
Licensed User
Longtime User
I think the reason is that you were trying to get views which are not visible and not initialized. I could be wrong. After making the changes below, it works for me.

B4X:
Sub clv2_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)   
    Dim ExtraSize As Int = 20 '
    smallestIndex=Max(0, FirstIndex - ExtraSize)
    largestIndex=Min(LastIndex + ExtraSize, clv2.Size - 1)

B4X:
For i = 0 To clv2.size - 1
        If i >=smallestIndex And i<largestIndex Then
            Dim p As B4XView = clv2.GetPanel(i)
            Log("i=" & i)
            Log(p.NumberOfViews)
            Dim chk As B4XView = p.GetView(1)  'Crash big time
            If chk.Checked Then
                Dim td As TestData =clv2.GetValue(i)
                checkedItems.Add(td.LabelText)
            End If
        End If
 next
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
After making the changes below, it works for me
It is not crashing, but it shows 0 checked items when I am checking a few with this line:
Log($"${checkedItems.Size} Checked items:${checkedItems}"$)

Can you maybe post the full 2 subs code you changed:
Sub clv2_VisibleRangeChanged and Sub btn_Click
Also, the scrolling is really slow for a list of only 200 items, unless release helps.
Or , if you have the project, you can post it with your changes.
Thanks
 
Upvote 0

toby

Well-Known Member
Licensed User
Longtime User
attached is the modified project
 

Attachments

  • xClvAutoTextSizeLabelChkBoxForForumModified.zip
    16.6 KB · Views: 109
Upvote 0

toby

Well-Known Member
Licensed User
Longtime User
The log below shows 5 checked items:

log:
5 Checked items:[BIBBY-DETELICH #1    10716, BYLER UNIT #1    1-883, CADWALLADER SONK MASTER #1    10181, CALLAHAN # 1    10537, CAMPBELL MASTER (GREAT LAKES)    10219]
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
The log below shows 5 checked items:
I could not run your project as it was missing the Class module and the Starter module, so I copied the 2 subs to my project and the result is the same. Crash at the same line. Did you make any other changes other the 2 subs for clv2_VisibleRangeChanged and Sub btn_Click , besides the 2 variables declared as Int in globals. This is strange, because I even tried it on another tablet and the result is crash and very slow scrolling. Please note that my project is B4A and does not share modules
 
Upvote 0

toby

Well-Known Member
Licensed User
Longtime User
It's your project with minor changes and i didn't add any file.

I basically keep track of the visible range when it 's changed, by adding the following two global variables:
B4X:
    Private smallestIndex As Int=0
    Private largestIndex As Int=0

then in clv2_VisibleRangeChanged, we update those two variables
B4X:
   Dim ExtraSize As Int = 20 ' your code
   'insert following two lines right after the above line'   
    smallestIndex=Max(0, FirstIndex - ExtraSize)
    largestIndex=Min(LastIndex + ExtraSize, clv2.Size - 1)

Finally, we ignore any request to get any views which are out of range in the following sub
B4X:
'modified version of your original sub'
Sub btn_Click
    Dim checkedItems As List
    checkedItems.Initialize
    For i = 0 To clv2.size - 1
        If i >=smallestIndex And i<largestIndex Then
            Dim p As B4XView = clv2.GetPanel(i)
            Dim chk As B4XView = p.GetView(1)  'Crash big time
            If chk.Checked Then
                Dim td As TestData =clv2.GetValue(i)
                checkedItems.Add(td.LabelText)
            End If
        End If
    Next
    Log($"${checkedItems.Size} Checked items:${checkedItems}"$)
    
End Sub

Hope that helps
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
I am still having problems with the same crash despite running it in 2 tablets. I am attaching the project that Toby made the corrections for. It is working for Toby but not for me.
 

Attachments

  • xClvAutoTextSizeLabelChkBoxThirdTry.zip
    16.6 KB · Views: 104
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The only correct answer is: you need to separate the UI from the program state.

It is quite simple to do:
1.
B4X:
Type TestData (LabelText As String, Checked As Boolean)
2.
B4X:
Sub clv2_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)
    Dim ExtraSize As Int = 20 '
    For i = Max(0, FirstIndex - ExtraSize) To Min(LastIndex + ExtraSize, clv2.Size - 1) 'Loop for adding/removing your items layout to or from the list
        Dim Pnl As B4XView = clv2.GetPanel(i) 
        If i > FirstIndex - ExtraSize And i < LastIndex + ExtraSize Then 'Add a new item to the list
            If Pnl.NumberOfViews = 0 Then '
                Dim TD As TestData = clv2.GetValue(i) 
                Pnl.LoadLayout("CellItem") 'Load your
                Label1.Text = TD.LabelText                
                Button1.SetColorAndBorder(Colors.RGB(255,100,0),2dip,Colors.Cyan,5dip)
                CheckBox1.Checked = TD.Checked '<-----------------
            End If
        Else 
            If Pnl.NumberOfViews > 0 Then
                Pnl.RemoveAllViews 'Remove none visible item from the main xCLV layout
            End If
        End If    
    Next
End Sub

3.
B4X:
Sub CheckBox1_CheckedChange(Checked As Boolean)
    Dim td As TestData = clv2.GetValue(clv2.GetItemFromView(Sender))
    td.Checked = Checked
End Sub

4.
B4X:
Sub btn_Click
    Dim checkedItems As List
    checkedItems.Initialize
    For i = 0 To clv2.size - 1
        Dim td As TestData = clv2.GetValue(i)
        If td.Checked Then
            checkedItems.Add(td)
        End If
    Next
    Log($"${checkedItems.Size} Checked items:${checkedItems}"$)
End Sub
 
Upvote 0
Top