Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-2621] Android: App crashes with paged tableview (1.5.x regression)

GitHub Issuen/a
TypeBug
PriorityLow
StatusClosed
ResolutionHold
Resolution Date2011-04-15T03:25:04.000+0000
Affected Version/sn/a
Fix Version/sRelease 1.6.0
ComponentsAndroid
Labelsandroid, crash, defect, regression, release-1.6.0, tableview
ReporterRobby
AssigneeDon Thorp
Created2011-04-15T03:25:04.000+0000
Updated2017-03-03T07:05:39.000+0000

Description

My app shows a list of games in a tableview. If there are more than 20, it will page the output. By this, I mean that it loads the first 20, then will have a 'touch for more' row at the bottom. When that is touched it will remove that row, and load 20 more. It loads these by creating the row objects (each with a unique className) and then calling a setData on the uploaded rowData list after all of the rows are created and added to the list.

This works fine on iOS AND on Android build version=1.4.2 timestamp=10/11/10 19:02 githash=425bc37, but I'm getting a weird crash bug on the 1.5.1 General release (version=1.5.1 timestamp=12/16/10 16:25 githash=16bbb92) after loading the second page of games into the table. What happens is that I click the row to load more, more games are loaded (that works fine) and then as I scroll around (up or down), within 5-10 seconds the app will crash with the following exception:

[TRACE] D/AndroidRuntime( 628): Shutting down VM
[TRACE] W/dalvikvm( 628): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
[TRACE] E/TiUncaughtHandler( 628): (main) [8606,794666] Sending event: exception on thread: main msg:java.lang.ArrayIndexOutOfBoundsException; Titanium 1.5.1,2010/12/16 16:25,6bbb92
[TRACE] E/TiUncaughtHandler( 628): java.lang.ArrayIndexOutOfBoundsException
[TRACE] E/TiUncaughtHandler( 628): at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:4078)
[TRACE] E/TiUncaughtHandler( 628): at android.widget.AbsListView.trackMotionScroll(AbsListView.java:2915)
[TRACE] E/TiUncaughtHandler( 628): at android.widget.AbsListView.onTouchEvent(AbsListView.java:2065)
[TRACE] E/TiUncaughtHandler( 628): at android.widget.ListView.onTouchEvent(ListView.java:3315)
[TRACE] E/TiUncaughtHandler( 628): at android.view.View.dispatchTouchEvent(View.java:3766)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:897)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/TiUncaughtHandler( 628): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1671)
[TRACE] E/TiUncaughtHandler( 628): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
[TRACE] E/TiUncaughtHandler( 628): at android.app.Activity.dispatchTouchEvent(Activity.java:2086)
[TRACE] E/TiUncaughtHandler( 628): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1655)
[TRACE] E/TiUncaughtHandler( 628): at android.view.ViewRoot.handleMessage(ViewRoot.java:1785)
[TRACE] E/TiUncaughtHandler( 628): at android.os.Handler.dispatchMessage(Handler.java:99)
[TRACE] E/TiUncaughtHandler( 628): at android.os.Looper.loop(Looper.java:123)
[TRACE] E/TiUncaughtHandler( 628): at android.app.ActivityThread.main(ActivityThread.java:4627)
[TRACE] E/TiUncaughtHandler( 628): at java.lang.reflect.Method.invokeNative(Native Method)
[TRACE] E/TiUncaughtHandler( 628): at java.lang.reflect.Method.invoke(Method.java:521)
[TRACE] E/TiUncaughtHandler( 628): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
[TRACE] E/TiUncaughtHandler( 628): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
[TRACE] E/TiUncaughtHandler( 628): at dalvik.system.NativeStart.main(Native Method)
[TRACE] I/TiApplication( 628): (main) [141,794807] Analytics are disabled, ignoring postAnalyticsEvent
[TRACE] E/AndroidRuntime( 628): FATAL EXCEPTION: main
[TRACE] E/AndroidRuntime( 628): java.lang.ArrayIndexOutOfBoundsException
[TRACE] E/AndroidRuntime( 628): at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:4078)
[TRACE] E/AndroidRuntime( 628): at android.widget.AbsListView.trackMotionScroll(AbsListView.java:2915)
[TRACE] E/AndroidRuntime( 628): at android.widget.AbsListView.onTouchEvent(AbsListView.java:2065)
[TRACE] E/AndroidRuntime( 628): at android.widget.ListView.onTouchEvent(ListView.java:3315)
[TRACE] E/AndroidRuntime( 628): at android.view.View.dispatchTouchEvent(View.java:3766)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:897)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
[TRACE] E/AndroidRuntime( 628): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1671)
[TRACE] E/AndroidRuntime( 628): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
[TRACE] E/AndroidRuntime( 628): at android.app.Activity.dispatchTouchEvent(Activity.java:2086)
[TRACE] E/AndroidRuntime( 628): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1655)
[TRACE] E/AndroidRuntime( 628): at android.view.ViewRoot.handleMessage(ViewRoot.java:1785)
[TRACE] E/AndroidRuntime( 628): at android.os.Handler.dispatchMessage(Handler.java:99)
[TRACE] E/AndroidRuntime( 628): at android.os.Looper.loop(Looper.java:123)
[TRACE] E/AndroidRuntime( 628): at android.app.ActivityThread.main(ActivityThread.java:4627)
[TRACE] E/AndroidRuntime( 628): at java.lang.reflect.Method.invokeNative(Native Method)
[TRACE] E/AndroidRuntime( 628): at java.lang.reflect.Method.invoke(Method.java:521)
[TRACE] E/AndroidRuntime( 628): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
[TRACE] E/AndroidRuntime( 628): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
[TRACE] E/AndroidRuntime( 628): at dalvik.system.NativeStart.main(Native Method)

This ONLY happens after loading an additional page of results (which at that point I have 40 rows, with 40 different class names). It also only happens when I am using unique class names for each row. If I use the same className, I don't get the crash, however I need unique classnames as I will modify the row label colors on a per-row basis when clicked (if I don't have this, I'll get weird undefined results).

Given the nature of this bug, I'm not so sure I can develop a test case for it. I did find the following:
http://kevinmorey.com/post/990223225/arrayindexoutofboundsexception-with-custom-android"> http://kevinmorey.com/post/990223225/arrayindexoutofboundsexception... http://stackoverflow.com/questions/2596547/arrayindexoutofboundsexception-with-custom-android-adapter-for-multiple-views-in"> http://stackoverflow.com/questions/2596547/arrayindexoutofboundsexc...

Perhaps one of those may point in the right direction. I can provide access to my code if necessary to aid with fixing of the bug.

Comments

  1. Robby 2011-04-15

    Did some further experimentation: This bug has nothing to do with the paging of the tableview. As an attempted workaround, I modified the code to load all 50 (in this case) rows at once (e.g. create 50 rows, add to rowData list, do a single setData() call), and still ran into the same bug when scrolling. My thinking is that there is some kind of bug that imposes a "limit" with the number of unique className values. If you go over that "limit", this bug manifests.

  2. Don Thorp 2011-04-15

    Couple of things. 1, you're going to get very slow performance with unique classNames per row. It effectively means that you're going to use a ton of memory and won't be able to show many rows in the long run.

    The tableview is currently maxed out at 32 unique classnames 3 of which are reserved for internal use.

    Try going back to using unique classNames, but make sure you put defaults on every row. For example. If you're changing text color on the label. Make sure you put that property on every row with a default value.

  3. Robby 2011-04-15

    Thanks Don...good to know I was on track with what the problem was. If you decide to keep this limit, perhaps raising a more explicit exception when running into too many classNames may help.

    Changing text label color and row backgroundColor on click (to show the row as "selected") is why I use the unique classNames, actually. I'd love to avoid using unique ones actually, if at all possible. I tried modifying the className to a "gameRowSelected" value when it was selected (so I effectively have 2 classNames total) but that doesn't work...still get weird unpredictable results...guessing you can't modify className dynamically like that.

    So if I have Labels on my rows that I need to modify the color of on a row by row basis, I basically have to use unique classNames?

  4. Robby 2011-04-15

    Also, if you say that the max # of unique classNames is 32 - 3, then I'm kind of at a deadend if I use unique classNames (since many of my screens have > 29 rows). Does that putting the defaults on every row effectively "get around" this issue, though? Just a bit confused on what the best approach is here....

  5. Don Thorp 2011-04-15

    Rows get reused if they have the same className. That allows for better memory utilization by have at most n+2 rows view hierarchy allocated to that className. Where n is the max number of rows visible on the screen at any one time for that className. Since you're changing attributes on the rows, you should be able to use a single className, but make sure that each row has the full set of attributes you want to control. For example if you're setting color on a text view to red and that row is scrolled off the screen, we need a color to set the row to when its views are used to display another rows worth of data.

    I haven't tested this, but you might be able to have a two classNames one for selected rows and one for the rest. Then update the selected row to use the new selected row className so that when you scroll around, the row proxies (TableViewRow) have the appropriate className and will draw correctly.

  6. Sean McCullough 2011-04-15

    I am having this error: http://developer.appcelerator.com/question/110421/repeating-dataindex-out-of-bounds-on-tableview-with-lots-of-unique-data"> http://developer.appcelerator.com/question/110421/repeating-dataind...

    Is there a solution to showing more than 29 unique rows of data?

  7. Lee Morris 2017-03-03

    Closing ticket due to time passed and irrelevance.

JSON Source