German xCustomListView ist sehr langsam bei nur 300 Datensätzen

JOTHA

Well-Known Member
Licensed User
Hallo zusammen,

Erel schrieb bei der Veröffentlichung der xCustomListView, dass diese bis zu einer größeren Menge an Datensätzen noch sehr schnell im Aufbau sein sollte.

Ich bin jetzt von einer "normalen" ListView, die ca. 300 Datensätze aus einer SQLite-Datenbank in weniger als 1 Sekunde aufgebaut hat, auf eine xCustomListView umgestiegen.

Diese benötigt jetzt aber für den Aufbau der gleichen Datensätze ca. 34 Sekunden (das ist für die App aber entscheiden zu lange!) !!!

Es geht dabei um die Darstellung folgender Informationen aus der SQLite:
6 Textfelder und 2 Verlinkungen zu Bildern (diese liegen in einem internen Ordner vor).

Hier ist der Code:
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

Sub Process_Globals

    Dim SQL1 As SQL
    Dim Cursor As Cursor

End Sub

Sub Globals
    
    Private xCustomListView As CustomListView
    Private Panel_003a_Label_Ueberschrift As Label  '-- eine Initialisierung ist zwar unnötig, aber bei der Ausführung der App wird ein ERROR generiert --
    Private Panel_003a_Label_001 As Label
    Private Panel_003a_ImageView_014 As ImageView
    Private Panel_003a_Label_002 As Label
    Private Panel_003a_ImageView_009 As ImageView
    Private Panel_003a_Label_014 As Label
    Private Panel_003a_Label_Hinweis As Label
    Private Panel_003a_Label_004 As Label
    Private Panel_003a_Label_IDNR As Label
    
End Sub

Sub Activity_Create(FirstTime As Boolean)
    
    Log("Kopiere die Datenbank in File.DirRootExternal")

    File.Copy(File.DirAssets, "SQLite_MUSTER.sl3", _
                    File.DirRootExternal, "SQLite_MUSTER.sl3")
    Log("Datenbank in File.DirRootExternal kopiert!")

    If FirstTime Then
        SQL1.Initialize(File.DirRootExternal, "SQLite_MUSTER.sl3", True)
    End If
    If SQL1.IsInitialized = False Then
        SQL1.Initialize(File.DirRootExternal, "SQLite_MUSTER.sl3", True)
    End If
    SQL1.Initialize(File.DirRootExternal, "SQLite_MUSTER.sl3", True)

    Activity.LoadLayout("layout_003_datensaetze_zeigen")
    
    xCustomListView.Clear
    
'-- Überschrift einfügen und View initialisieren --
    Panel_003a_Label_Ueberschrift.Initialize("CreateListItem")
    Panel_003a_Label_001.Initialize("CreateListItem")  '-- eine Initialisierung ist zwar unnötig, aber bei der Ausführung der App wird ein ERROR generiert --
    Panel_003a_Label_002.Initialize("CreateListItem")
    Panel_003a_Label_014.Initialize("CreateListItem")
    Panel_003a_Label_004.Initialize("CreateListItem")
    Panel_003a_Label_IDNR.Initialize("CreateListItem")
    Panel_003a_Label_Hinweis.Initialize("CreateListItem")
    Panel_003a_ImageView_009.Initialize("CreateListItem")
    Panel_003a_ImageView_014.Initialize("CreateListItem")
    
    Cursor = SQL1.ExecQuery ("SELECT * FROM MUSTER_Tabelle")
        
    Try
        SQL1.BeginTransaction

        For i = 0 To Cursor.RowCount - 1
            Cursor.Position = i
            
        '-- Zähler für die Auswahlliste generieren --
            Dim Counter As String
            Counter = i +1
            
        '-- die xCustomListView aufbauen --
            xCustomListView.Add(CreateListItem(Panel_003a_Label_Ueberschrift.Text, Activity.Width, 315dip), ""&Cursor.GetString("IDNR")&"")
            
        '-- wenn keine Internet-Adresse vorhanden ist -- Feld007 --
            If Cursor.GetString("Feld007") = "- keine Internet-Adresse -" Then
                Panel_003a_Label_Ueberschrift.Text = "  "&Counter&". Datensatz ist OHNE Internet-Zugang"
                Panel_003a_Label_Ueberschrift.Color = Colors.Red
            Else If Cursor.GetString("Feld007") = "" Then
                Panel_003a_Label_Ueberschrift.Text = "  "&Counter&". Datensatz ist OHNE Internet-Zugang"
                Panel_003a_Label_Ueberschrift.Color = Colors.Red
            Else
                Panel_003a_Label_Ueberschrift.Text = "  "&Counter&". Datensatz ist MIT Internet-Zugang"
                Panel_003a_Label_Ueberschrift.Color = Colors.Blue
            End If
            
        '-- Daten_in_die_xCustomListView_einfuegen --
            Daten_in_die_xCustomListView_einfuegen
            Log("-----------------------------------------------------------------------------")
            Log(""&Counter&". Datensatz gelistet")

        Next
        SQL1.TransactionSuccessful
    Catch
        Log(""&LastException.Message&"")
    End Try
    SQL1.EndTransaction
    Cursor.Close

End Sub

Sub xCustomListView_ItemClick (Index As Int, Value As Object)
    Activity.Title = Value
    xCustomListView.AsView.BringToFront
End Sub

Sub Daten_in_die_xCustomListView_einfuegen

'-- Daten in die Textelder zuweisen --
    Panel_003a_Label_001.Text = ""&Cursor.GetString("Feld001")&""
    Panel_003a_Label_002.Text = "Benutzer:"&CRLF&""&Cursor.GetString("Feld002")&""
    Panel_003a_Label_004.Text = "Kategorie:"&CRLF&""&Cursor.GetString("Feld004")&""
    Panel_003a_Label_IDNR.Text = "ID: "&Cursor.GetString("IDNR")&""
        
'-- Eigenes Bild zuweisen -- Feld014 --
    Log("Eigenes Bild zuweisen - Feld014: "&Cursor.GetString("Feld014")&"")
    If File.Exists(File.DirAssets, ""&Cursor.GetString("Feld014")&"") Then
        Panel_003a_Label_014.Text = "Ein Bild ist vorhanden"
        Panel_003a_ImageView_014.Bitmap = LoadBitmap(File.DirAssets, ""&Cursor.GetString("Feld014"))
        Panel_003a_Label_014.Typeface = Typeface.DEFAULT
    Else
        Panel_003a_Label_014.Text = "Es ist KEIN Bild vorhanden!"
    End If
            
'-- Kategorie-Icon zuweisen -- Feld009 --
    Log("Kategorie-Icon zuweisen - Feld009: "&Cursor.GetString("Feld014")&"")
    If File.Exists(File.DirAssets, ""&Cursor.GetString("Feld009")&"") Then
        Log("If FILE EXISTST ==> "&File.Exists(File.DirAssets, ""&Cursor.GetString("Feld009")&"")&"")
        Panel_003a_Label_014.Text = "Ein Bild ist vorhanden"
        Panel_003a_ImageView_009.Bitmap = LoadBitmap(File.DirAssets, ""&Cursor.GetString("Feld009"))
        Panel_003a_Label_014.Typeface = Typeface.DEFAULT
    Else
        Panel_003a_Label_004.Text = "Es ist KEIN Kategorie-Bild vorhanden!"
        Log("Inhalt von Feld009: "&Cursor.GetString("Feld009")&"")
        Log("Es ist KEIN Kategorie-Bild vorhanden!")
    End If

End Sub

Sub CreateListItem(Text As String, Width As Int, Height As Int) As Panel
    
    Dim p As Panel
    p.Initialize("")
    p.SetLayout(0, 0, Width, Height)
    p.LoadLayout("layout_003a_inhalt_p3_xclv3")
    Panel_003a_Label_001.Text = Text
    Return p
    
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Ich habe eine kleine Beispiel-App als zip-Datei zum Testen gepackt, aber leider kann ich diese nicht uploaden, da sie zu groß ist (743 kB). --> The uploaded file is too large. Gerne sende ich die Datei per Mail zu.

Kann mir jemand sagen woran das liegt, das es soooo lange dauert?
 

klaus

Expert
Licensed User
Versuche mal die Objects Datei in der Projekt Datei zu löschen, in manchen Fällen macht das einen Unterschied.
Ich habe kaum mit xCustomListView gearbeitet, aber trotz dem, 34 Sekunden kommt mir sehr langsam vor.
 

DonManfred

Expert
Licensed User
Entferne mal die 300 Transactions, den trycatch block.
Es hilft alles nichts wenn du nicht verstanden hast wie das mit den Objekten funktioniert die in einem Layout sind welches innerhalb von CreateItem geladen wird.
 

klaus

Expert
Licensed User
Hallo Klaus, kannst Du mir kurz erklären, was Du damit meinst?
In dem Project Ordner, wo die xxx.b4a Datei gespeichert ist, sint noch zwei Ordner drin.
Files und Objects, in manchen Fällen sind da grössere Dateien drin.
 

JOTHA

Well-Known Member
Licensed User
... Files und Objects, in manchen Fällen sind da grössere Dateien drin ...
Danke für deine Hilfe, Klaus.
Jetzt habe ich verstanden, was Du gemeint hast.

Ich habe den Objects-Ordner vollständig gelöscht und dann neu Kompiliert ... logischerweise hat die IDE dann den Ordner neu angelegt.
Zuvor habe ich nachgeschaut, welche Eigenschaften der Objects-Ordner hatte: 30 Dateien in 18 Ordnern mit 2,32 MB. Nach dem Kompilieren hat sich praktisch nichts verändert.

Die anschließend gepackte zip-Datei hat wieder eine Größe von 745 kB.
 

JOTHA

Well-Known Member
Licensed User
Ich meinte den Objects Ordner bevor dem zippen zu löschen.
... ach so, wegen dem upload!

Jetzt hats geklingelt!
Das habe ich jetzt gemacht und wollte im Anhang die zip-Datei zum Testen hochladen, aber wieder die gleiche Meldung, weil die Datei immer noch 666kB groß ist.

Zur Ausführung der App brauche ich aber den Files-Ordner, da in diesem die Icons sind, die in der xCustomViewList angezeigt werden sollen, sonst kommt eine Fehlermeldung ...

... also habe ich jetzt einfach ein paar Icons aus dem Files-Ordner gelöscht und dann mit 7-ZIP gepackt, jetzt kommen zwar auch Fehlermeldungen, aber zum Testen müsste es reichen.

Ich danke Dir vielmals für deine Hilfe!

Ich denke aber, das sich das Problem mit dem langsamen Aufbau mit "lazy" (aus dem Tutorial-Video) lösen lässt.
 

Attachments

  • xCustomListView-Testprogramm300b.zip
    352 KB · Views: 111

klaus

Expert
Licensed User
Ich hab ein bisschen mit deinem Programm gespielt.
Habe alle Log kommentiert.
Auf meinem Galaxy S8 brucht der Aufbau ungefähr 4 - 5 Sekunden.
Ich habe die Animation Duration in den Layouts auf 0 gesetzt.

Beiliegend das Programm mit meinen Versuchen.
 

Attachments

  • New.zip
    352.4 KB · Views: 134

Filippo

Expert
Licensed User
Hallo Jürgen,

4 tips von mir:
1) verwende LoadBitmapResize oder LoadBitmapSample statt LoadBitmap
2) lade nicht den Layout "layout_003a_inhalt_p3_xclv3", sondern erstelle es immer per code, es geht viel schneller
3) verwende nicht DirRootExternal (ab Android 6+ Berechtigungsprobleme), sondern DirDefaultExternal
4) In Manifest habe ich diese Zeile "SetApplicationAttribute(android:largeHeap, "true")" hinzugefügt, sonst kommt "memory-fehler"
 

JOTHA

Well-Known Member
Licensed User
Beiliegend das Programm mit meinen Versuchen
Hallo Klaus,
vielen Dank für deinen Test!

Bei meinem Smartphone dauert dieser Vorgang mit deinen Änderungen ca. 9 Sekunden (... es hat ja nicht jeder ein S8 ;)).

Das Auskommentieren einer "Log-Zeile" bringt ca. 1 Sekunde Zeitersparnis. Bei der Anzahl der Log's summiert sich das natürlich ...

Am meisten bremsen diese 2 Zeilen:
B4X:
Sleep(1)
Label1.Text = "Der "&(i +1)&". Datensatz wird eingelesen"
... dadurch dauert alles über 20 Sekunden länger!
--> aber ohne irgend eine Information im Display sind sogar "nur" 9 Sekunden für einen User zu lange ...

Ich werde jetzt mal die Tipps von Filippo (siehe oben: LoadBitmapResize und SetApplicationAttribute(android:largeHeap, "true")) ausprobieren, um zu sehen, was diese noch an Geschwindigkeitsvorteilen bringen könnten.

Vielen Dank Filippo und Klaus für eure Unterstützung!
 

JOTHA

Well-Known Member
Licensed User
Entferne mal die 300 Transactions, den trycatch block
Vielen Dank DonManfred für deine Hinweise!
Ich habe das was Du mir empfohlen hast getestet, leider hat es keinen merklichen Geschwindigkeitsvorteil gebracht ...
 

Filippo

Expert
Licensed User
Ich werde jetzt mal die Tipps von Filippo (siehe oben: LoadBitmapResize und SetApplicationAttribute(android:largeHeap, "true")) ausprobieren, um zu sehen, was diese noch an Geschwindigkeitsvorteilen bringen könnten.
Dieser Tipp bringt keine Geschwindigkeitsvorteile, es nur speicher schonend.
Geschwindigkeitsvorteile bringt nur Tipp 2!
 

JOTHA

Well-Known Member
Licensed User
Geschwindigkeitsvorteile bringt nur Tipp 2
Danke Filippo, ich habe das gerade eben getestet:
B4X:
Panel_003a_ImageView_014.Bitmap = LoadBitmapResize(File.DirAssets, Cursor.GetString("Feld014"), 40dip, 40dip, True)
... dauert sogar 1 Sekunde länger ...
B4X:
Panel_003a_ImageView_014.Bitmap = LoadBitmapSample(File.DirAssets, Cursor.GetString("Feld014"), 40dip, 40dip)
... dauert 8,93 Sekunden ... aber gegenüber 9,13 Sekunden ist das ja nun wirklich kein Geschwindigkeitsvorteil ... ;)

Jetzt baue ich mal den Code um mit deinem Tipp 2) lade nicht den Layout "layout_003a_inhalt_p3_xclv3"
Da bin ich gespannt ...
 

klaus

Expert
Licensed User
Dass LoadBitmapResize länger braucht als LoadBitmap hatte Ich bei menen Tests auch gesehen.
Ich hatte auch mal versucht die Bitmaps nicht zu lesen, brachte aber auch keinen grossen Vorteil.
Lazy loading bringt bestimmt etwas, habe es aber noch nie versucht.
Ich muss auch zugestehen dass Ich xCustumView auch nicht verwende.
 

MaFu

Well-Known Member
Licensed User
Am meisten bremsen diese 2 Zeilen:
B4X:
Sleep(1)
Label1.Text = "Der "&(i +1)&". Datensatz wird eingelesen"
... dadurch dauert alles über 20 Sekunden länger!
--> aber ohne irgend eine Information im Display sind sogar "nur" 9 Sekunden für einen User zu lange ...
Das könntest Du deutlich entschärfen indem Du die Info nur bei jedem 10ten oder 20ten Datensatz aktualisierst.
B4X:
If i Mod 10 = 0 Then
    Sleep(1)
    Label1.Text = "Der "&(i + 1)&". Datensatz wird eingelesen"
End If
 
Top