Android - 上下文菜单 - 由于 MenuBuilder$MenuAdapter 在没有收到通知的情况下更改 MenuBuilder$MenuAdapter 而出现异常

发布于 2024-10-08 13:47:15 字数 4090 浏览 0 评论 0原文

我进行了广泛的搜索,以找到当用户单击一个上下文菜单项然后重复单击另一个上下文菜单项时我们的应用程序崩溃的原因的答案。这是我的堆栈跟踪,全部在 Android 内部类上:

11-11 15:08:30.904: ERROR/AndroidRuntime(3489): FATAL EXCEPTION: main
11-11 15:08:30.904: ERROR/AndroidRuntime(3489): 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(16908808, class com.android.internal.app.AlertController$RecycleListView) with Adapter(class com.android.internal.view.menu.MenuBuilder$MenuAdapter)]
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.widget.ListView.layoutChildren(ListView.java:1550)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.widget.AbsListView.onTouchEvent(AbsListView.java:2192)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.widget.ListView.onTouchEvent(ListView.java:3377)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.View.dispatchTouchEvent(View.java:3766)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:897)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1720)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1117)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.app.Dialog.dispatchTouchEvent(Dialog.java:642)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1704)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1794)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.os.Looper.loop(Looper.java:143)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.app.ActivityThread.main(ActivityThread.java:4701)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at java.lang.reflect.Method.invokeNative(Native Method)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at java.lang.reflect.Method.invoke(Method.java:521)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at dalvik.system.NativeStart.main(Native Method)
11-11 15:08:30.912: WARN/ActivityManager(1261):   Force finishing activity com.pyxismobile.pyxWholesaler.ui.activity/.GNBActivity
11-11 15:08:30.943: WARN/WindowManager(1261): No window to dispatch pointer action 1
11-11 15:08:30.943: WARN/WindowManager(1261): No window to dispatch pointer action 0
11-11 15:08:30.943: WARN/WindowManager(1261): No window to dispatch pointer action 1

我们的基本设计是在 Activity 类上重写 onCreateContextMenu 和 onContextMenuItem。在创建时,代码基本上填充 MyMenuItems 的集合,其中每个项目都有一个 run 方法来执行我们需要菜单项执行的任何操作。 onContextMenuItem 基本上从传入的 MenuItem 中获取 ID,在集合中查找给定的 id,然后运行该 run 方法。

为了尝试缩小原因,我注释掉了运行部分,不执行任何操作。这仍然会导致异常。我没有看到创建和单击我们要修改任何数据的位置之间有任何特殊的情况。一切都在创作中完成一次。

我尝试创建一个非常简单的测试应用程序,但是我无法发生此异常。我还简单地查看了 Android 内部源代码,看看是否能找出任何东西,但什么也没发现。

如果有人对我可能做错了什么或者要调查什么有任何建议,我将不胜感激。

编辑:我还确定这是与设备无关的。我已经能够在多个设备上重新创建,但在极少数情况下不会发生。我的假设是存在某种竞争条件。

I've searched high and low to find an answer to why our application is crashing when a user will click on one Context Menu item and then repeatedly clicks on another. Here is the stack trace I have, which is all on Android internal classes:

11-11 15:08:30.904: ERROR/AndroidRuntime(3489): FATAL EXCEPTION: main
11-11 15:08:30.904: ERROR/AndroidRuntime(3489): 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(16908808, class com.android.internal.app.AlertController$RecycleListView) with Adapter(class com.android.internal.view.menu.MenuBuilder$MenuAdapter)]
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.widget.ListView.layoutChildren(ListView.java:1550)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.widget.AbsListView.onTouchEvent(AbsListView.java:2192)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.widget.ListView.onTouchEvent(ListView.java:3377)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.View.dispatchTouchEvent(View.java:3766)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:897)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:936)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1720)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1117)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.app.Dialog.dispatchTouchEvent(Dialog.java:642)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1704)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1794)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.os.Looper.loop(Looper.java:143)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at android.app.ActivityThread.main(ActivityThread.java:4701)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at java.lang.reflect.Method.invokeNative(Native Method)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at java.lang.reflect.Method.invoke(Method.java:521)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-11 15:08:30.904: ERROR/AndroidRuntime(3489):     at dalvik.system.NativeStart.main(Native Method)
11-11 15:08:30.912: WARN/ActivityManager(1261):   Force finishing activity com.pyxismobile.pyxWholesaler.ui.activity/.GNBActivity
11-11 15:08:30.943: WARN/WindowManager(1261): No window to dispatch pointer action 1
11-11 15:08:30.943: WARN/WindowManager(1261): No window to dispatch pointer action 0
11-11 15:08:30.943: WARN/WindowManager(1261): No window to dispatch pointer action 1

The basic design we have is on an Activity class we override the onCreateContextMenu and onContextMenuItem. On the create, the code basically populate a collection of MyMenuItems where each item has a run method to execute whatever we need the menu item to do. The onContextMenuItem basically takes the ID from the MenuItem passed in, looks up on the collection the given id, and then just runs that run method.

To try and narrow down what the cause is, I've commented out the run portion to do nothing. This still causes the exception. I didn't see anything special going between the creation and clicking where we would modify any data. Everything is done once in the creation.

I tried to create a very simple test app, however I could not get this exception to occur. I've also briefly looked at the internal Android source code to see if I could figure out anything, but nothing came to light.

If anyone has any suggestions on what I may be doing wrong, or what to look into it would be appreciated.

Edit: I've also determined for this to be device agnostic. I have been able to recreate on multiple devices, however on rare occasion it does not happen. My assumption is there is some sort of race condition.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

很糊涂小朋友 2024-10-15 13:47:15

设置一个 myMenuAdapter.registerDataSetObserver(DataSetObserverobserver) (API 此处)在发生更改时进行记录,并尝试使用连接到运行 adb logcat 的 PC 的手机来复制错误。这可能会为您提供修改时间的线索。

您是否还可以再次初始化适配器而不是重用它?

Set up a myMenuAdapter.registerDataSetObserver(DataSetObserver observer) (API here) to log when the change occur and try to replicate the error with the phone connected to a PC running adb logcat. That may give you a clue for when it is being modified.

Can it be also that you are initializing again an adapter instead of reusing it?

非要怀念 2024-10-15 13:47:15

添加到ListView后尽量不要更改适配器。

如果在使用过程中仍需要更改 ListView 的内容,则 在适配器更新期间将 ListView 的可见性设置为“消失”,并在更新后恢复为“可见”。

Try not to change the adapter after you add it to ListView.

If you still need to change the contents of ListView during it's use, than set the visibility of your ListView to GONE during adapter update and back to VISIBLE after the update.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文