[TIMOB-20038] Android: TableView crashes when scrolling more than 29 rows
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Critical |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2016-02-02T08:33:21.000+0000 |
Affected Version/s | titanium 5.0.5 |
Fix Version/s | Release 5.2.0 |
Components | Android |
Labels | android |
Reporter | Adam Fennell |
Assignee | Hieu Pham |
Created | 2015-10-07T14:33:08.000+0000 |
Updated | 2016-04-11T13:19:19.000+0000 |
Description
When executing the following code, if there are more than 29 rows, the app will crash when scrolling back up from the bottom of the TableView:
(You may need to try more than 30 rows for the app to crash, as each device may vary this number)
var section = Ti.UI.createTableViewSection();
var numberOfRows = 30; //if > 29 the app will crash when scrolling back up from the bottom
for (var i=0; i < numberOfRows; i++)
{
//fill section with rows
section.add(Ti.UI.createTableViewRow({
height: 50,
width: Ti.UI.FILL,
backgroundColor: 'green',
className: 'row' + i
}));
};
var table = Ti.UI.createTableView({
top: 0,
left: 0,
height: Ti.UI.FILL,
width: Ti.UI.FILL,
data: [ section ]
});
var window = Ti.UI.createWindow({
fullscreen: true
});
window.add(table);
window.open();
*The error log from the Studio console is:*
[ERROR] : InputEventReceiver: Exception dispatching input event.
[DEBUG] : AndroidRuntime: Shutting down VM
[WARN] : dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x410532a0)
[ERROR] : TiApplication: (main) [25408,25408] Sending event: exception on thread: main msg:java.lang.ArrayIndexOutOfBoundsException: length=32; index=32; Titanium 3.5.1,2015/03/05 10:08,96875c9
[ERROR] : TiApplication: java.lang.ArrayIndexOutOfBoundsException: length=32; index=32
[ERROR] : TiApplication: at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:7127)
[ERROR] : TiApplication: at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5694)
[ERROR] : TiApplication: at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3424)
[ERROR] : TiApplication: at android.widget.AbsListView.onTouchEvent(AbsListView.java:4099)
[ERROR] : TiApplication: at android.view.View.dispatchTouchEvent(View.java:7350)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2464)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
[ERROR] : TiApplication: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
[ERROR] : TiApplication: at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2151)
[ERROR] : TiApplication: at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1480)
[ERROR] : TiApplication: at android.app.Activity.dispatchTouchEvent(Activity.java:2469)
[ERROR] : TiApplication: at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.dispatchTouchEvent(ActionBarActivityDelegateICS.java:268)
[ERROR] : TiApplication: at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2099)
[ERROR] : TiApplication: at android.view.View.dispatchPointerEvent(View.java:7535)
[ERROR] : TiApplication: at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3492)
[ERROR] : TiApplication: at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3424)
[ERROR] : TiApplication: at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4534)
[ERROR] : TiApplication: at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4512)
[ERROR] : TiApplication: at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4616)
[ERROR] : TiApplication: at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
[ERROR] : TiApplication: at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
[ERROR] : TiApplication: at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:163)
[ERROR] : TiApplication: at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4584)
[ERROR] : TiApplication: at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4635)
[ERROR] : TiApplication: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
[ERROR] : TiApplication: at android.view.Choreographer.doCallbacks(Choreographer.java:555)
[ERROR] : TiApplication:
[ERROR] : TiApplication: at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
[ERROR] : TiApplication: at android.os.Handler.handleCallback(Handler.java:615)
[ERROR] : TiApplication: at android.os.Handler.dispatchMessage(Handler.java:92)
[ERROR] : TiApplication: at android.os.Looper.loop(Looper.java:137)
[ERROR] : TiApplication: at android.app.ActivityThread.main(ActivityThread.java:4921)
[ERROR] : TiApplication: at java.lang.reflect.Method.invokeNative(Native Method)
[ERROR] : TiApplication: at java.lang.reflect.Method.invoke(Method.java:511)
[ERROR] : TiApplication: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
[ERROR] : TiApplication: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
[ERROR] : TiApplication: at dalvik.system.NativeStart.main(Native Method)
I have tried removing the "className" property from the TableViewRow, which stops the crashing, but prevents Buttons and other Views inside the TableViewRow redrawing correctly, so must be left in (as indicated by the Appcelerator Platform Docs).
Due to our customers using JellyBean devices, we need the fix in 3.5.1 or 3.5.2, as the devices can't be upgraded to newer Android versions.
*Possible Cause:*
This may be caused by an issue with 0-Based indexes used in getItemViewType() or getViewTypeCount() in titanium_mobile/android/modules/ui/src/java/ti/modules/titanium/ui/widget/listview/TiListView.java
Could you let me know if this is something you are looking into? It would be great if I could update our customers, as this is a work stop issue for them.
The problem here is this:
"className" is used for internal recycling purposes (i.e: speeds up loading time for table view). Currently we support up to 32 different classNames (or row layouts). In your example, there is only one row layout, so you only need one className. Please look at http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.TableViewRow-property-className for more info. I will expose a property to change the default '32', but for this case you should only use one className.
Thanks for looking into this. The example code I posted was to highlight the issue. In our actual app, we have (or would like to have) 40 rows with different layouts i.e. no rows have the same layout of views. Am I right to say then: 1. We would use: *className: 'row' + i* ? 2. We would set the newly exposed property from 32 to 40? Also, would there be a negative effect on performance or memory consumption if this exposed property is, for example, set to 100?
master PR: https://github.com/appcelerator/titanium_mobile/pull/7558 testing code:
PR merged. Adding https://github.com/appcelerator/titanium_mobile/pull/7561 to update doc from
6.0.0
to5.2.0
.Doc PR merged.
Following are my observations I found while checking the fix: If "maxClassName" is set to two more or less than the number of rows then the app crashes while scrolling up from the bottom. If "maxClassName" is set to three or more than the number of rows then the app does not crash while scrolling up from the bottom. Reopening Tested on: iPhone 6s Plus Device (9.1) Mac OSX El Capitan 10.11.2 (15C50) Studio: 4.4.0.201511241829 Ti SDK: 5.2.0.v20160114021251 Appc NPM: 4.2.2 App CLI: 5.2.0-224 Xcode 7.2 Node v4.2.4
Josh, that is because we have some default class names mapping as well. Like I said, the use case for "maxClassname" is not practical in the scenario described above. You should only use 1 className per row UI, not row, for performance purposes.
The application is crashing still even without scrolling
Load the application
Rotate or open multitasking
the app crashes
2 things. If the use case is not practical for "maxClassname" can we: 1. Describe in documentation of the proper use of maxClassname 2. fail elegantly instead of crashing if maxClassname is misused.
Verified the fix. There is no crash when
maxClassName
is is set to two more or less than the number of rows. Closing. Environment: Appc Studio : 4.5.0.201602070910 Ti SDK : 5.2.0.v20160208101502 Ti CLI : 5.0.6 Alloy : 1.7.33 MAC Yosemite : 10.10.5 Appc NPM : 4.2.3-2 Appc CLI : 5.2.0-249 Node: 4.2.2 Nexus 5 - Android 5.1.1