Android Example Change DataSet in Amir_RecyclerView

During the basic training in Amir_RecyclerView (ARV), a small test project was created, which may help RV newcomers to familiarize themselves with RecyclerViews.

Topic: "React to clickevents, change data and update the list"

19-09-_2018_08-52-28.jpg

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

' ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--..
'
'    Ref1) Info lib --> https://www.b4x.com/android/forum/threads/lib-chargeable-amir_recyclerview.97274/#post-613329
'
'    Ref2) Info Android Dev --> https://developer.android.com/reference/android/support/v7/widget/RecyclerView
'
'    Ref3) Info Codepath RV --> https://guides.codepath.com/android/Using-the-RecyclerView
'
' ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--..
'
#Region ---- Relationship of the RV components ----

'        +----------------------+
'        | RecyclerView         |
'        |                      |                                   
'        |                      |                                   
'        |+--------------------+|  +--------------+  +-------------+ 
'        || LayoutManager      ||  |              |  |             | 
'        ||                    ||  |              |  |             | 
'        ||                    ||  |              |  |             | 
'        ||                   -----|   Adapter    |--|   DataSet   | 
'        ||                    ||  |              |  |             | 
'        ||                    ||  |              |  |             | 
'        |+--------------------+|  |              |  |             | 
'        +----------------------+  +--------------+  +-------------+ 
'                                                                          Created with --> http://www.torchsoft.com/en/aas_information.html 
#end region

Sub Process_Globals
End Sub
Sub Globals
    Type arvItem(Title As String, Description As String)
    Private arv As Amir_RecyclerView
    Private DataSet As List
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Log("#-Sub Activity_Create")
    Activity.Color = Colors.White
    arvBuild
    arvFill
End Sub

Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
'
Sub arvBuild
    Log("#-Sub arvBuild")
    arv.Initializer("arv").ListView.Build
    arv.DefaultAdapter
    Activity.AddView(arv, 0, 0, 100%x, 100%y)
End Sub

Sub arvFill
    Log("#-Sub arvFill")
    DataSet.Initialize
    For i = 0 To 9
        Dim arvItemX As arvItem
        arvItemX.Initialize
        arvItemX.Title = "Entry " & i
        arvItemX.Description = "Lorem ipsum to entry " & i
        DataSet.Add(arvItemX)
    Next
    arv.Adapter2.NotifyDataSetChanged
End Sub

Sub arv_GetItemCount As Int
    Log("#-Sub arv_GetItemCount, DataSet.Size=" & DataSet.Size)
    Return DataSet.Size    ' This is for the Adapter
End Sub

Sub arv_onCreateViewHolder (Parent As Panel, ViewType As Int)
    Log("#-Sub arv_onCreateViewHolder, ViewType=" & ViewType)
 
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    ' This creates a panel for each list item without filling in the content
    ' The content will be filled later in "..._onBindViewHolder"
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    Parent.LoadLayout("1")
 
End Sub
Sub arv_onBindViewHolder (Parent As Panel, Position As Int)
   Log("#-Sub arv_onBindViewHolder, Position=" & Position)
 
   ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
   ' This fills the item content from the Dataset
   ' corresponding to the position
   ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
   Dim panBack As Panel = Parent.GetView(0)
   Dim Label1 As Label = panBack.GetView(0)
   Dim Label2 As Label = panBack.GetView(1)

   Dim arvItemX As arvItem = DataSet.Get(Position)
   '
   Label1.Text = arvItemX.Title
   Label2.Text = arvItemX.Description & CRLF & "Position=" & Position
 
   panBack.Height = Label1.Height +Label2.Height +(Label1.Top *2) 
   Parent.Height = panBack.Height +8dip
 
End Sub

Sub arv_onItemClick (Parent As Panel, Position As Int)
   Log("#-Sub arv_onItemClick, Position=" & Position)
 
   '--- --- --- --- --- --- --- --- --- --- --- --- ---
   'Example: CHANGE content in underlying Data
   '      and inform the Adapter
   '--- --- --- --- --- --- --- --- --- --- --- --- ---
   Dim arvItemX As arvItem = DataSet.Get(Position)
   arvItemX.Title = arvItemX.Title & ", click"

   DataSet.Set(Position, arvItemX)
   arv.Adapter2.NotifyDataItemChanged(Position)
 
   '--- --- --- --- --- --- --- --- --- --- --- --- ---
 
End Sub

Sub arv_onItemLongClick (Parent As Panel, Position As Int) As ResumableSub
   Log("#-Sub arv_onItemLongClick, Position=" & Position)
 
   ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
   ' Example: DELETE content in underlying Data
   '                 and inform the Adapter
   ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
   Dim arvItemX As arvItem = DataSet.Get(Position)
   Msgbox2Async($"Delete the item '${arvItemX.Title}'?"$, $"Delete item '${arvItemX.Title}'"$, "Yes", "Cancel", "No", Null, False)
   Wait For Msgbox_Result (Result As Int)
   If Result = DialogResponse.POSITIVE Then
    
       DataSet.RemoveAt(Position)
       arv.Adapter2.NotifyItemRemoved(Position)
       arv.Adapter2.NotifyDataItemChanged2(Position, Position +arv.GetVisibleItemCount)  ' Needed to inform the Layout manager to refresh the visible items BELOW the clicked item
    
       ToastMessageShow($"'${arvItemX.Title}' removed from list"$, False)
   End If
 
   Return Null
End Sub

Edit: The attached testproject was updated. Now the proposal of @alimanam3386 to notify the adapter after changing the DataSet is integrated.

In principle, you should notify the adapter after a change to the DataSet so that a suitable animation is displayed and the administration cache of the displayed items is updated:​

B4X:
DataSet.RemoveAt(Position)
arv.Adapter2.NotifyItemRemoved(Position)
arv.Adapter2.NotifyDataItemChanged2(Position, Position +arv.GetVisibleItemCount)  ' Needed to inform the Layout manager to refresh the visible items BELOW the clicked item
 

Attachments

  • ARV_Testproject_SimpleRv.zip
    10.2 KB · Views: 183
Last edited:

alimanam3386

Active Member
Licensed User
During the basic training in Amir_RecyclerView (ARV), a small test project was created, which may help RV newcomers to familiarize themselves with RecyclerViews.

Topic: "React to clickevents, change data and update the list"


B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

' ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--..
'
'    Ref1) Info lib --> https://www.b4x.com/android/forum/threads/lib-chargeable-amir_recyclerview.97274/#post-613329
'
'    Ref2) Info Android Dev --> https://developer.android.com/reference/android/support/v7/widget/RecyclerView
'
'    Ref3) Info Codepath RV --> https://guides.codepath.com/android/Using-the-RecyclerView
'
' ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--.. ~~--..
'
#Region ---- Relationship of the RV components ----

'        +----------------------+
'        | RecyclerView         |
'        |                      |                                     
'        |                      |                                     
'        |+--------------------+|  +--------------+  +-------------+   
'        || LayoutManager      ||  |              |  |             |   
'        ||                    ||  |              |  |             |   
'        ||                    ||  |              |  |             |   
'        ||                   -----|   Adapter    |--|   DataSet   |   
'        ||                    ||  |              |  |             |   
'        ||                    ||  |              |  |             |   
'        |+--------------------+|  |              |  |             |   
'        +----------------------+  +--------------+  +-------------+   
'                                                                          Created with --> http://www.torchsoft.com/en/aas_information.html   
#end region

Sub Process_Globals
End Sub
Sub Globals
    Type arvItem(Title As String, Description As String)
    Private arv As Amir_RecyclerView
    Private DataSet As List
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Log("#-Sub Activity_Create")
    Activity.Color = Colors.White
    arvBuild
    arvFill
End Sub

Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
'
Sub arvBuild
    Log("#-Sub arvBuild")
    arv.Initializer("arv").ListView.Build
    arv.DefaultAdapter
    Activity.AddView(arv, 0, 0, 100%x, 100%y)
End Sub

Sub arvFill
    Log("#-Sub arvFill")
    DataSet.Initialize
    For i = 0 To 9
        Dim arvItemX As arvItem
        arvItemX.Initialize
        arvItemX.Title = "Entry " & i
        arvItemX.Description = "Lorem ipsum to entry " & i
        DataSet.Add(arvItemX)
    Next
    arv.Adapter2.NotifyDataSetChanged
End Sub

Sub arv_GetItemCount As Int
    Log("#-Sub arv_GetItemCount, DataSet.Size=" & DataSet.Size)
    Return DataSet.Size    ' This is for the Adapter
End Sub

Sub arv_onCreateViewHolder (Parent As Panel, ViewType As Int)
    Log("#-Sub arv_onCreateViewHolder, ViewType=" & ViewType)
 
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    ' This creates a panel for each list item without filling in the content
    ' The content will be filled later in "..._onBindViewHolder"
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    Parent.LoadLayout("1")
 
End Sub
Sub arv_onBindViewHolder (Parent As Panel, Position As Int)
    Log("#-Sub arv_onBindViewHolder, Position=" & Position)
 
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    ' This fills the item content from the Dataset
    ' corresponding to the position
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    Dim panBack As Panel = Parent.GetView(0)
    Dim Label1 As Label = panBack.GetView(0)
    Dim Label2 As Label = panBack.GetView(1)

    Dim arvItemX As arvItem = DataSet.Get(Position)
    Label1.Text = arvItemX.Title
    Label2.Text = arvItemX.Description

    panBack.Height = Label1.Height +Label2.Height +(Label1.Top *2)
    Parent.Height = panBack.Height +8dip
 
End Sub

Sub arv_onItemClick (Parent As Panel, Position As Int)
    Log("#-Sub arv_onItemClick, Position=" & Position)
 
    ' --- --- --- --- --- --- --- --- --- --- --- --- ---
    ' Example: CHANGE content in underlying Data
    '           and inform the Adapter
    ' --- --- --- --- --- --- --- --- --- --- --- --- ---
    Dim arvItemX As arvItem = DataSet.Get(Position)
    arvItemX.Title = arvItemX.Title & ", click"
    DataSet.Set(Position, arvItemX)
 
    arv.Adapter2.NotifyDataItemChanged(Position)
    ' --- --- --- --- --- --- --- --- --- --- --- --- ---
 
End Sub

Sub arv_onItemLongClick (Parent As Panel, Position As Int) As ResumableSub
    Log("#-Sub arv_onItemLongClick, Position=" & Position)
 
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    ' Example: DELETE content in underlying Data
    '                  and inform the Adapter
    ' --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
    Dim arvItemX As arvItem = DataSet.Get(Position)
    Msgbox2Async($"Delete the item '${arvItemX.Title}'?"$, $"Delete item '${arvItemX.Title}'"$, "Yes", "Cancel", "No", Null, False)
    Wait For Msgbox_Result (Result As Int)
    If Result = DialogResponse.POSITIVE Then
        DataSet.RemoveAt(Position)
        ' arv.Adapter2.NotifyItemRemoved(Position)    ' This is somehow not working, since the next click on an item than refers to a wrong item...
        arv.Adapter2.NotifyDataSetChanged ' This works. But it should only be used as a last resort according to Codepath RV --> https://guides.codepath.com/android/Using-the-RecyclerView#notifying-the-adapter
        ToastMessageShow($"'${arvItemX.Title}' removed from list"$, False)
    End If
 
    Return Null
End Sub


Use ARV.Adapter2.NotifyItemRemoved(position) instead arv.Adapter2.NotifyDataSetChanged

B4X:
Private adapter As dcKeyValueList ' DataCollection lib
....
....
...

Sub lblTag_LongClick
    Dim l As Label = Sender
    Dim typeInfo As item = l.Tag
    Dim position As Int = adapter.IndexOfKey(typeInfo.id)
    adapter.Remove(typeInfo.id)
    LV.Adapter2.NotifyItemRemoved(position)
End Sub
 
Last edited:
Top