[TIMOB-16968] Android: App crashes due to ListView modifications
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Critical |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2014-05-21T19:25:39.000+0000 |
Affected Version/s | n/a |
Fix Version/s | 2014 Sprint 10, 2014 Sprint 10 SDK, Release 3.3.0, Release 3.4.0 |
Components | Android |
Labels | android, crash, listview, module_kitchensink, qe-testadded, triage |
Reporter | Mark Mokryn |
Assignee | Hieu Pham |
Created | 2014-05-05T06:48:22.000+0000 |
Updated | 2014-07-29T23:55:01.000+0000 |
Description
On occasion I am seeing app crashes with the log below. Unfortunately, I have not been able to reproduce this in a simple test case, but it does happen on occasion in my app, during certain sequences. The issue is clearly stated in the error log: the ListView has been modified outside the UI thread.
Reviewing the ListView code, there are several places where such issues can occur. In ListSectionProxy.java, for example the following methods *definitely* modify the ListView without first making sure the UI thread is running:
setHeaderView
, setFooterView
, setHeaderTitle
, and setFooterTitle
. And indeed - *the issues in my code went away* after I stopped calling setHeaderTitle
. Note that these methods ensure the UI thread is running only to call adapter.notifyDataSetChanged()
, but the changes themselves may clearly be made outside the UI thread - which is a bug.
Additionally - I'm not sure that setting the ListView.sections property is UI thread safe.
I strongly suggest Appcelerator reviews ListView code to ensure it is all UI thread safe.
{color:red}
05-04 19:03:15.566: E/AndroidRuntime(9698): FATAL EXCEPTION: main
05-04 19:03:15.566: E/AndroidRuntime(9698): java.lang.IllegalStateException: *The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread.* [in ListView(-1, class android.widget.ListView) with Adapter(class android.widget.HeaderViewListAdapter)]
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.ListView.layoutChildren(ListView.java:1510)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.AbsListView.onLayout(AbsListView.java:1260)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
05-04 19:03:15.566: E/AndroidRuntime(9698): at ti.modules.titanium.ui.widget.listview.TiListView$ListViewWrapper.onLayout(TiListView.java:139)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at org.appcelerator.titanium.view.TiCompositeLayout.onLayout(TiCompositeLayout.java:580)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1589)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at org.appcelerator.titanium.view.TiCompositeLayout.onLayout(TiCompositeLayout.java:580)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1254)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1130)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.LinearLayout.onLayout(LinearLayout.java:1047)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1254)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1130)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.LinearLayout.onLayout(LinearLayout.java:1047)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.View.layout(View.java:7175)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.ViewRoot.performTraversals(ViewRoot.java:1140)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.os.Handler.dispatchMessage(Handler.java:99)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.os.Looper.loop(Looper.java:130)
05-04 19:03:15.566: E/AndroidRuntime(9698): at android.app.ActivityThread.main(ActivityThread.java:3683)
05-04 19:03:15.566: E/AndroidRuntime(9698): at java.lang.reflect.Method.invokeNative(Native Method)
05-04 19:03:15.566: E/AndroidRuntime(9698): at java.lang.reflect.Method.invoke(Method.java:507)
05-04 19:03:15.566: E/AndroidRuntime(9698): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
05-04 19:03:15.566: E/AndroidRuntime(9698): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
05-04 19:03:15.566: E/AndroidRuntime(9698): at dalvik.system.NativeStart.main(Native Method)
{color}
See pull request: https://github.com/appcelerator/titanium_mobile/pull/5658 My issues have been fixed for now by this PR, but I still urge Appcelerator to review all the ListView code to make sure there are no further manifestations of this bug. Specifically - is the creation dictionary being handled in the UI thread? See explanation of why this PR is required: https://github.com/mokesmokes/titanium_mobile/commit/1b88f411ef87449343a51af6d301dc629290f26b
No comment from Appcelerator on an issue that causes app crashes???
Mark, we have a number of tickets coming in from different sources as we wind down 3.3.0 and I was not alerted to this one yet. I've placed it into triage. Thank you for following up.
That's fine. Just a quick overview to help you guys with this one: all I did was modify the 4 offending ListSection methods that were not written in the usual pattern of running methods on the UI thread - very straight forward and the review should be simple. Unfortunately as this is a threading/timing issue the crash is not easy to replicate - even debug prints can move the timing one way or another, also device dependent, etc - but it definitely was happening on occasion and this fixed it.
3.3.X PR: https://github.com/appcelerator/titanium_mobile/pull/5720
[~hpham] - can you please provide any test steps/code to verify the fix for this ticket.
Testing steps: Run KS -> views -> list views -> headers and footers, make sure everything is working as expected.
Verified the fix by running test in KS -> views -> list views -> headers and footers & did not find any issues. Closing. Environment: Appc Studio : 3.3.0.201406171619 Ti SDK : 3.3.0.v20140617161713 Mac OSX : 10.8.5 Alloy : 1.4.0-rc CLI - 3.3.0-rc Code Processor: 1.1.1 Samsung Galaxy S4 - android 4.2.2