Android Question Large listview crashes on Android 7

jpvniekerk

Active Member
Licensed User
Longtime User
I have an app that crashes on a customer's S8 phone (Android 7) opening a listview that contains a lot (> 1400) of items. A filtered list with < 100 items works fine.
I don't have a device with Android 7, but on Android 6 I don't get the problem at all, so I can't replicate the issue to debug myself.

My code for filling the listview is:
B4X:
If cur2.IsInitialized Then cur2.Close
If vFavPL = 0 Then
      sqlTxt = "SELECT ID, Name, Manf_ID FROM tblComp WHERE Type = 4 ORDER by Name COLLATE NOCASE"
    Else
      sqlTxt = "SELECT ID, Name, Manf_ID FROM tblComp WHERE Type = 4 AND Fav = 1 ORDER by Name COLLATE NOCASE"
    End If
cur2 = sql1.ExecQuery(sqlTxt)
For i = 0 To cur2.RowCount - 1
    cur2.Position = i
    lvPickList.AddSingleLine2(cur2.GetString("Name") &" ("&getManfAbbr(cur2.GetInt("Manf_ID"))&")",cur2.GetInt("ID"))
Next

If vFavPL = 0 (full list of ~1400 items) app crashes.
If vFavPL = 1 (~100 items) app does not crash.

Any ideas why this might happen?
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
First guess is that the device is running out of memory. Is the user seeing an error message, or are you getting crash reports in your Google Play console? Have you tried running it on a simulator running Nougat?

I was going to offer to test it for you, but then I realized that my only device that was running Nougat was updated to Oreo recently & all my other devices are either Marshmallow or earlier.

- Colin.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

jpvniekerk

Active Member
Licensed User
Longtime User
Is the user seeing an error message, or are you getting crash reports in your Google Play console?
It was first reported by a user (app just crashed without an error message), but when I looked at the Google Play Console the crashes are shown there as well. I have a mechanism to catch app errors and send me email with the log as described here: https://www.b4x.com/android/forum/threads/uncaught-exceptions.59805/#content - but I haven't received any emails about these crashes: another thing that bothers me - why does that part not work?

Have you tried running it on a simulator running Nougat?
No - I use hard connected device for testing - had a lot of issues with the simulators in the past, but I will give it a try again.
Thanks for the offer!

Hiding the full stacktrace does not help us to help you.
Not hiding... didn't have any until they showed up on Google Play Console. Here's the list shown there:

android.database.CursorIndexOutOfBoundsException:
at android.database.AbstractCursor.checkPosition (AbstractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosition (AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString (AbstractWindowedCursor.java:50)
at anywheresoftware.b4a.sql.SQL$CursorWrapper.GetString (SQL.java:355)
at com.lynxdvm.vaporsuite.main._vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv1 (main.java:15192)
at com.lynxdvm.vaporsuite.main._vvvvvvv6 (main.java:24575)
at com.lynxdvm.vaporsuite.main._btna2_click (main.java:4836)
at java.lang.reflect.Method.invoke (Native Method)
at anywheresoftware.b4a.BA.raiseEvent2 (BA.java:169)
at anywheresoftware.b4a.BA.raiseEvent2 (BA.java:157)
at anywheresoftware.b4a.BA.raiseEvent (BA.java:153)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick (ViewWrapper.java:78)
at android.view.View.performClick (View.java:6261)
at android.widget.TextView.performClick (TextView.java:11157)
at android.view.View$PerformClick.run (View.java:23748)
at android.os.Handler.handleCallback (Handler.java:751)
at android.os.Handler.dispatchMessage (Handler.java:95)
at android.os.Looper.loop (Looper.java:154)
at android.app.ActivityThread.main (ActivityThread.java:6776)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1410)
 
Upvote 0

jpvniekerk

Active Member
Licensed User
Longtime User
It seems that you use a Cursor with a database and you set Cursor.Position to a value out of bounds !?

That's what it seems like, but I cannot figure out from the code (shown above) what is wrong. And I've tested it on other devices, and have probably run that code 1000's of times - without an error. So the code works - the only time I got this error was one user and one device!

I've now also tested it on a physical device (note 6) with Android 7 and cannot replicate the crash...:mad:
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
Are you sure the error is coming from the code you posted? You can open your main.java file & take a look at the line of code referred to in the stack trace:
at com.lynxdvm.vaporsuite.main._vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv1 (main.java:15192)
& see if it's what you think it is.

The java files will be in "[your project dir]/Objects/src/com/lynxdvm/vaporsuite/".

- Colin.
 
Upvote 0

jpvniekerk

Active Member
Licensed User
Longtime User
Thanks Colin @Computersmith64
Did some more digging in the Java file. Finally came to the code that this line came from.
B4X:
Sub getManfAbbr(tmpID As Int) As String
    sqlTxt = "SELECT Abbr FROM tblManf WHERE ID = '"&tmpID&"'"
    If cur3.IsInitialized Then cur3.Close
    cur3 = sql1. ExecQuery(sqlTxt)
    cur3.Position = 0
    Return cur3.GetString("Abbr")
End Sub
I've double-checked the data, and there should never be a situation where cur3 is empty. This code runs on 100's of devices without problems!

I also have this code in the formatting of the listview:
B4X:
    Dim r As Reflector
    r.Target = lvPickList
    Dim CD As ColorDrawable
    CD.Initialize(col3, 0)
    r.RunMethod4("setDivider", Array As Object(CD), Array As String("android.graphics.drawable.Drawable"))
    r.RunMethod2("setDividerHeight", 2, "java.lang.int")

According to the user, after setting the filter to "0", the app takes a couple of seconds, seemingly doing nothing, and then crashes. I'm groping at straws here - totally stumped with this crash!
 
Upvote 0

jpvniekerk

Active Member
Licensed User
Longtime User
The problem was solved - had nothing to do with the code... Apparently the db was corrupted. Un-installed and re-installed and the problem is gone!

Thanks for all your help!

Note that you should never build queries like this. Use ExecQuery2 with a parameterized query.
Why would that be @Erel ?
For more complex queries I do use ExecQuery2, but for simple "one-liners" I just use ExecQuery. Always want to learn more and why certain things are better.
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User

Attachments

  • upload_2017-8-23_7-19-40.png
    upload_2017-8-23_7-19-40.png
    168.1 KB · Views: 210
Last edited:
Upvote 0

jpvniekerk

Active Member
Licensed User
Longtime User
@Erel Thanks!
I will change my code according to your suggestion. And good to know for the future. I "only" have about 100 changes to make in my current app!
 
Upvote 0

jpvniekerk

Active Member
Licensed User
Longtime User
What about when no parameters are passed such as this?
B4X:
    sqlTxt = $"
    SELECT
    tblDiary.ID,
    tblDiary.DateTime,
    tblDiary.Action,
    tblDiary.Hardw_ID,
    tblHardw.Name AS HwName,
    tblDiary.Coil_ID,
    tblJrCoil.Name AS CoilName,
    tblJrCoil.Price AS CoilPrice,
    tblDiary.Juice_ID,
    tblJrJuice.Name AS JuiceName,
    tblJrJuice.Price AS JuicePrice,
    tblDiary.Volume,
    tblDiary.Note
    FROM tblDiary
    LEFT JOIN tblHardw ON tblHardw.id = tblDiary.Hardw_ID
    LEFT JOIN tblJrCoil ON tblJrCoil.id = tblDiary.Coil_ID
    LEFT JOIN tblJrJuice ON tblJrJuice.id = tblDiary.Juice_ID
    ORDER by DateTime Desc
    "$
    If cur1.IsInitialized Then cur1.Close
    cur1 = sql1.ExecQuery(sqlTxt)
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
What about when no parameters are passed such as this?

When you have a lengthy query that involves several tables or queries, it is always neater and easier to read and less prone to errors when you give your tables aliases. See your query statement below using table aliases:
B4X:
sqlTxt = $"
    SELECT
    D.ID,
    D.DateTime,
    D.Action,
    D.Hardw_ID,
    H.Name AS HwName,
    D.Coil_ID,
    C.Name AS CoilName,
    C.Price AS CoilPrice,
    D.Juice_ID,
    J.Name AS JuiceName,
    J.Price AS JuicePrice,
    D.Volume,
    D.Note
    FROM tblDiary D
    LEFT JOIN tblHardw  H ON H.id = D.Hardw_ID
    LEFT JOIN tblJrCoil C ON C.id = D.Coil_ID
    LEFT JOIN tblJrJuice J ON J.id = D.Juice_ID
    ORDER by D.DateTime Desc
    "$
 
Upvote 0
Top