Android – setVisibility导致java.util.ConcurrentModificationException

前端之家收集整理的这篇文章主要介绍了Android – setVisibility导致java.util.ConcurrentModificationException前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我通过setVisibility(View.INVISIBLE)隐藏视图.稍后,当我尝试通过setVisibility(View.VISIBLE)以不同的方法再次显示视图时,我得到以下异常 @H_301_2@03-28 01:32:05.450: E/AndroidRuntime(20895): FATAL EXCEPTION: main 03-28 01:32:05.450: E/AndroidRuntime(20895): java.util.ConcurrentModificationException 03-28 01:32:05.450: E/AndroidRuntime(20895): at java.util.HashMap$HashIterator.nextEntry(HashMap.java:796) 03-28 01:32:05.450: E/AndroidRuntime(20895): at java.util.HashMap$KeyIterator.next(HashMap.java:823) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:946) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:948) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:948) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:948) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:948) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:948) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewRoot.handleDragEvent(ViewRoot.java:3027) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.view.ViewRoot.handleMessage(ViewRoot.java:2185) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.os.Handler.dispatchMessage(Handler.java:99) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.os.Looper.loop(Looper.java:132) 03-28 01:32:05.450: E/AndroidRuntime(20895): at android.app.ActivityThread.main(ActivityThread.java:4028) 03-28 01:32:05.450: E/AndroidRuntime(20895): at java.lang.reflect.Method.invokeNative(Native Method) 03-28 01:32:05.450: E/AndroidRuntime(20895): at java.lang.reflect.Method.invoke(Method.java:491) 03-28 01:32:05.450: E/AndroidRuntime(20895): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) 03-28 01:32:05.450: E/AndroidRuntime(20895): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) 03-28 01:32:05.450: E/AndroidRuntime(20895): at dalvik.system.NativeStart.main(Native Method)

当我注释掉将可见性更改为可见的行时,我没有得到异常.

我首先想到异常是由一些其他代码迭代通过一个hashmap引起的,但是,我在迭代我使用的hashmaps时没有做任何修改,也没有多线程,这似乎是最常见的原因.这个例外.当我不改变能见度时,我也没有得到例外.

编辑:
自定义片段中发生异常.下面是我遍历hashmap(mWidgetConfig)的代码,其中包含有关我尝试恢复的自定义窗口小部件配置的信息. hashmap是片段中的公共变量.

在由片段创建的OnDragListener中,我根据某个拖动操作更新了hashmap,如下所示:

@H_301_2@// Update the widget configuration of the fragment that created this listener mFragment.mWidgetConfig.put(startCircleTag,"0");

我还迭代了hashmap来检查某个条件,但是在迭代期间我没有做任何修改

@H_301_2@Iterator<String> keySetItr = mFragment.mWidgetConfig.keySet().iterator(); while(keySetItr.hasNext()) { String tag = keySetItr.next(); if(mFragment.mWidgetConfig.get(tag).equals((String) destSocket.getTag())) { // do something,though no modification of the hashmap break; } }

另外,在尝试恢复小部件配置时,我在片段本身中进行了一次迭代.下面是我根据hashmap配置窗口小部件的代码

@H_301_2@public void configureWidgets() { resetWidgets(); Iterator<String> keySetItr = mWidgetConfig.keySet().iterator(); while(keySetItr.hasNext()) { String tag = keySetItr.next(); Integer value = Integer.parseInt(mWidgetConfig.get(tag)); ImageView destSocket = null; switch(value) { case 0: // The circle will not be connected to any socket continue; case 1: destSocket = mSocket1; break; case 2: destSocket = mSocket2; break; case 3: destSocket = mSocket3; break; } ImageView startCircle = (ImageView) mLayout.findViewWithTag(tag); ImageView startPlug = (ImageView) mLayout.findViewWithTag(tag + "_plug"); // Replace the drawable of destSocket destSocket.setBackgroundDrawable(getActivity().getResources().getDrawable(R.drawable.socket_plugged)); // Hide plug view startPlug.setVisibility(View.INVISIBLE); // Draw a line between the start circle view and the destination socket view mConnectionLinesView.addLine(startCircle,destSocket); } } public void resetWidgets() { // Remove all lines mConnectionLinesView.removeLines(); // Show all eventually prevIoUsly hidden plugs //mPlug1.setVisibility(View.VISIBLE); //mPlug2.setVisibility(View.VISIBLE); //mPlug3.setVisibility(View.VISIBLE); // Set to backround drawable of the socket to the initial one mSocket1.setBackgroundDrawable(getActivity().getResources().getDrawable(R.drawable.socket).mutate()); mSocket2.setBackgroundDrawable(getActivity().getResources().getDrawable(R.drawable.socket).mutate()); mSocket3.setBackgroundDrawable(getActivity().getResources().getDrawable(R.drawable.socket).mutate()); }

一旦在代码中使用了设置上面“插件”可见性的行,我就会得到异常.


抛出异常的原因是我在OnDragListener的DragEvent.ACTION_DRAG_ENDED case语句中调用了配置方法.当我将相同的代码放入DragEvent.ACTION_DROP case语句时,不会抛出异常.不知道为什么.谢谢你的帮助

解决方法

据我所知,这是由ViewGroup实现细节引起的.而且它与多线程无关.

拖动开始时,ViewGroup会创建一个子视图的HashSet,必须通知ACTION_DRAG_ENDED事件.这是一组可见的孩子.当子可见性发生变化时,相应的ViewGroup会修改该集合(如果子集的可见性是可见的,则添加子集).在您的情况下,它会在迭代过程中发生.

想想,最简单的解决方案是推迟可见性变化.

@H_301_2@view.post(new Runnable() { public void run() { view.setVisibility(View.VISIBLE); } });

代码放入ACTION_DROP case语句时不会发生异常,因为在更改视图可见性时不会迭代该集合.

有关详细信息,请参阅ViewGroup.dispatchDragEvent(DragEvent)代码.

猜你在找的Android相关文章