Android的 - setVisibility结果java.util.ConcurrentModificationException [英] Android - setVisibility results in java.util.ConcurrentModificationException

查看:243
本文介绍了Android的 - setVisibility结果java.util.ConcurrentModificationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我躲在通过 setVisibility视图(View.INVISIBLE)。后来,当我试图通过 setVisibility(View.VISIBLE)再次显示视图在一个不同的方法对我得到下面的异常

I am hiding a view via setVisibility(View.INVISIBLE). Later on when I try to show the view again in a different method via setVisibility(View.VISIBLE) I get the following exception

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)

当我注释掉改变能见度回到可见行了,我不明白的例外。

When I comment out the line that changes the visibility back to visible, I don't get the exception.

我首先想到的异常会被其他一些code通过HashMap的迭代造成的,但是,我不同时,通过我用的是包含HashMap迭代做任何修改,我也不具有多线程,这似乎是最常见的原因的异常。此外,我没有得到异常的时候我换不回的知名度。

I first thought that the exception would be caused by some other code iterating through a hashmap, however, I don't do any modifications while iterating through the hashmaps I use, neither do I have multithreading, which seem to be the most common reason for this exception. Also I don't get the exception when I don't change back the visibility.

修改
在定制的片断时,会出现异常。下面是code,我遍历HashMap中( mWidgetConfig ),其中包含用户控件,我想要恢复的配置信息。 HashMap的是在片段的公共变量。

EDIT:
The exception occurs in a custom fragment. Below is the code where I iterate over the hashmap (mWidgetConfig) that contains information about the configuration of custom widgets that I am trying to restore. The hashmap is a public variable in the fragment.

OnDragListener 这是由片段创建的,我按照一定的拖动操作更新HashMap的,像这样的:

In an OnDragListener which is created by the fragment, I update the hashmap according to a certain drag operation, like this:

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

我还遍历HashMap中检查一定的条件,但我不迭代过程中做任何修改:

I also iterate over the hashmap to check a certain condition but I don't do any modification during the iteration:

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;

            }
        }

此外,我做一次迭代的片段本身,而试图恢复窗口小部件配置。下面是code我用根据HashMap来配置窗口小部件:

In addition I do one iteration in the fragment itself while trying to restore the widget configuration. Below is the code I use to configure the widget according to the hashmap:

    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());
}

一旦这个设置上面在code中使用的插头的知名度线,我得到的异常。

As soon as the lines that set the visibility of the "plugs" above are used in the code, I get the exception.

解决方案:
除了得到抛出的理由是,我打电话 DragEvent.ACTION_DRAG_ENDED 情况下, OnDragListener 的声明的配置方法。当我把同样的code到 DragEvent.ACTION_DROP case语句中的异常不抛出。不知道为什么。感谢您的帮助球员

SOLUTION
The reason the exception got thrown is that I called the configuration methods in the DragEvent.ACTION_DRAG_ENDED case statement of the OnDragListener. When I put the same code into the DragEvent.ACTION_DROP case statement the exception doesn't get thrown. No clue why. Thanks for your help guys

推荐答案

据我了解,这是通过的ViewGroup 实施细节造成的。这不是多线程连接。

As I understand this is caused by ViewGroup implementation details. And it's not connected with multithreading.

当拖动启动的ViewGroup 创建子视图HashSet的,必须通知有关 ACTION_DRAG_ENDED 事件。这是一组可见子。当孩子能见度变了相应的的ViewGroup 修改该集(增加一个孩子,如果它的能见度可见)。而在你的情况下,它在迭代通过该集合发生。

When drag starts ViewGroup creates a HashSet of child views that must be notified about ACTION_DRAG_ENDED event. This is a set of visible children. When child visibility is changed a corresponding ViewGroup modifies that set (adding a child if its visibility is VISIBLE). And in your case it happens during iterations over that collection.

想想,你最简单的解决办法就是推迟能见度变化。

Think, the easiest solution for you is to postpone the visibility change.

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

而当你把你的code到 ACTION_DROP case语句,因为该组没有被重复了的时候,你改变了看法可见异常不会发生。

And exception does not happen when you put your code into the ACTION_DROP case statement because that set is not being iterated at the moment you change the view visibility.

有关详细信息,请参阅<一href="https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/ViewGroup.java#L1100">ViewGroup.dispatchDragEvent(DragEvent)来源$ C ​​$ C。

For details see ViewGroup.dispatchDragEvent(DragEvent) source code.

这篇关于Android的 - setVisibility结果java.util.ConcurrentModificationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆