Android Question Slow Scrollview

RandomCoder

Well-Known Member
Licensed User
Longtime User
I've searched the forum and it would appear that I need to use either a Tableview or Informatix's UltimateListView to get improved performance. I'd just like to check with those more knowledgeable than I which would be the easiest way to proceed, i.e. require the least modifications to my existing code?

My app uses a Map to store information received from browse requests to a media server. The key is the ID of the object returned by the server and the value is a custom Type detailing the name of the object, and other information.
What I have at present is a Scrollview loaded with Panels, each Panel has an Imageview to the left side and a label to the right. This works fine when only a few items are contained in the Map, but slows significantly when 100's of items are present. I've attempted to use a DoEvents after every 20 panels (see refreshCount variable), but this had NO effect at all.
B4X:
Private Sub ShowDeviceItems(itemStartPosition As Int)
    Dim psv As Panel
    Dim i , listBottom, fontSize, fontHeader, fontItem, refreshCount As Int
    psv = svDiscoveredList.Panel
    fontHeader = 35
    fontItem = 20
    refreshCount = 0
    ' Show all items from browsed results
    If UPNP.browseResults.Size > 0 Then
        ' Remove all previous items if starting a new list
        If itemStartPosition = 0 Then
            psv.RemoveAllViews
            scrollingLabels.Initialize
            listBottom = 0
        Else
            listBottom = psv.Height
        End If
        ' Add each item to scroll view
        For i = itemStartPosition To UPNP.browseResults.Size - 1
            Dim container As itemContainer
            container.Initialize
            Dim pContainer As Panel
            Dim ivIcon As ImageView
            Dim lItem As Label
            Dim id, name, itemClass As String
            container = UPNP.browseResults.GetValueAt(i)
            id = UPNP.browseResults.GetKeyAt(i)
            name = container.title
            itemClass = container.itemClass
            fontSize = fontHeader
           
            pContainer.Initialize("ViewItem")
            pContainer.Tag = id
            psv.AddView(pContainer, 0, listBottom, psv.Width, 80dip)
            pContainer.Color = Colors.DarkGray

            ' Show item icon
            ivIcon.Initialize("ViewDevice")
            ivIcon.Tag = id
            pContainer.AddView(ivIcon, 10dip, 10dip, 60dip, 60dip)
            If itemClass.Contains("object.container") Then
                If name.ToLowerCase.Contains("movie") OR name.ToLowerCase.Contains("video") Then
                    ivIcon.Bitmap = LoadBitmapSample(File.DirAssets, "movies folder.png", 60, 60)
                Else If name.ToLowerCase.Contains("music") Then
                    ivIcon.Bitmap = LoadBitmapSample(File.DirAssets, "music folder.png", 60, 60)
                Else If name.ToLowerCase.Contains("picture") OR name.ToLowerCase.Contains("photo") Then
                    ivIcon.Bitmap = LoadBitmapSample(File.DirAssets, "pictures folder.png", 60, 60)
                Else
                    ivIcon.Bitmap = LoadBitmapSample(File.DirAssets, "folder.png", 60, 60)
                End If
            Else If itemClass.Contains("object.item") Then
                fontSize = fontItem
                If itemClass.Contains("video") Then
                    'ivIcon.Bitmap = LoadBitmapSample(File.DirAssets, "movies file.png", 60, 60)
                    ivIcon.Bitmap = LoadBitmap(File.DirAssets, "movies file.png")
                Else If itemClass.Contains("image") Then
                    ivIcon.Bitmap = LoadBitmapSample(File.DirAssets, "pictures file.png", 60, 60)
                Else If itemClass.Contains("audio") Then
                    ivIcon.Bitmap = LoadBitmapSample(File.DirAssets, "music file.png", 60, 60)
                End If
            End If

            ' Show item name
            lItem.Initialize("ViewItem")
            lItem.Tag = id
            pContainer.AddView(lItem, 100dip, 1dip, Activity.Width-101dip, 79dip)
            lItem.TextSize = fontSize
            lItem.Color = Colors.DarkGray
            lItem.Typeface = Typeface.DEFAULT_BOLD
            lItem.Gravity = Gravity.CENTER_VERTICAL
            If name <> Null Then
                lItem.Text = name
                'scrollingLabels.Add(Scrolling_Labels.StartScrolling(lItem, name, True))
            End If

            listBottom = pContainer.Top + 85dip
        Next
        svDiscoveredList.Panel.Height = listBottom
        refreshCount = refreshCount + 1
        If refreshCount = 20 Then
            refreshCount = 0
            DoEvents
        End If
    End If
End Sub
All advice greatly appreciated.

Thanks,
RandomCoder
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Always use 'dip' units with LoadBitmapSample.
2. Use LoadBitmapSample instead of LoadBitmap.
3. Reuse the same bitmaps. Don't load the same file multiple times. Load them once and store them as global bitmaps.
4. Test it without the DoEvents call.
5. I recommend you to use CustomListView class instead of ScrollView.

Try these suggestions and then test the speed again (in Release mode).
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
Thanks for the suggestions guys, I'll give them a try later tonight.
With regard to the LoadBitmapSample instead of LoadBitmap, you'll notice that I commented out the line above which was LoadBitmapSample when loading the "movies file.png". This was bacause I scaled the image down so that it was already the correct size to use, thus saving the call to LoadBitmapSample and hoping to reduce some of the overhead when loading a long list of movies. Your suggestion to store the images as a global bitmap is certain to have a positive effect and I know that removing the DoEvents will have no effect as this was only added as a last ditch attempt last night.
I've not used the CustomListView but will check it out.

@eps,
Please can you explain what is meant by bump scrolling?

Thanks,
RandomCoder.
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
I've not tried the CustomListView yet but can report a significant speed improvement by loading the Bitmaps as Globals and reusing them in the Scrollview. One question that has arose is that after changing the LoadBitmapSample from a height and width of 60 to 60dip, the image was too big for the Imageview which is also set to 60dip by 60dip. Please can you explain why this is? One of the image files is attached and as you can see, it has a transparent area around the image and a shadow underneath. To get it to display the same as when scaled to a height and width of 60, I've had to use 30dip. I just expected that if the Imageview is 60dip by 60dip then it would be logical to scale the image to the same size?

Changing orientation is still a little slow, taking approx 4 seconds to respond to the change of orientation and display the Scrollview. But this is probably because I'm looping through +1000 titles in one go. I might be able to speed this up by loading the Scrollview with 100 items at a time which is what happens initially when browsing the media server. The DoEvents command appears to have no effect (and so I've removed it), although I recall a problem with using DoEvents on a Scrollview which caused it not to scroll. This no longer appears to be the case, as my Scrollview worked just the same.

I do intend to try the CustomListView, just haven't had chance tonight. And with regard to bump-scrolling, I've Google'd what this means and not found an answer.

Thanks,
RandomCoder

movies folder.png
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
Can you extract the list related code to a new project and upload it (with the required data)?
I'm at work at the moment but will try later tonight. I believe that I can write a Map to file although I've never done it before, so it should be easy enough to create a sample app just with the Scrollview and list of data.

Kind regards,
RandomCoder
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
To anyone kind enough to have a look at my attached sample code, the Map data was taken directly from a UPNP Media Control Point App that I am tinkering with. The problem I have is that the Scrollview is slow to update when the screen is rotated. The App gives the impression as though it has hung as it takes approximately 4 seconds before the screen orientation changes and the Scrollview data is displayed. In the attached sample I've had to mess with the File.ReadMap values because they were returned as a String but my original Map stores the values in a custom data Type. Once the sample program has loaded, you will see the delay by simply changing the orientation of the device.
I have an idea how to improve performance which is to use a timer to load 100 items at a time into the Scrollview, this is kind of like what happens when the list is initially being populated by browse results received from a Media Server.
Does anyone have any better ideas?

Thanks,
RandomCoder
 

Attachments

  • ScollviewTest.zip
    25.5 KB · Views: 223
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The problem is that you are creating more than 3000 views when the activity is created.

You can switch to a solution as described here: customlistview loads max items and loads more when scroll tot bottom
New items are added when the user reaches the last item.

You can also use the standard ListView or UltimateListView which do not create a view for each item.
 
  • Like
Reactions: eps
Upvote 0
Top