java.util.ConcurrentModificationException在View.setVisibilityutil、java、ConcurrentModificationExceptio

2023-09-04 13:05:35 作者:曾经的你、送走谁的思念の未来的你、吹散谁的泪水

我在执行拖放的意见。当拖动操作开始,我将视图的可视性看不见,然后,如果拖动被打断 - 回可见

I'm implementing drag'n'drop for views. When drag is started, I set visibility of the view to INVISIBLE, then, if the drag was interrupted - back to VISIBLE:

public boolean onTouch(View v, MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        // Skipped some code
        boolean dragStarted = v.startDrag(data, shadowBuilder, v, 0);

        if (dragStarted) {
            v.setVisibility(View.INVISIBLE)
        }
    }
}

if (event.getAction() == DragEvent.ACTION_DRAG_ENDED) {
    View droppedView = (View) event.getLocalState();
    droppedView.setVisibility(View.VISIBLE);
}

当拖动结束事件被称为,我得到异常:

And when "Drag ended" event is called, I'm getting exception:

E/AndroidRuntime(7118): FATAL EXCEPTION: main 
E/AndroidRuntime(7118): java.util.ConcurrentModificationException 
E/AndroidRuntime(7118):     at java.util.HashMap$HashIterator.nextEntry(HashMap.java:792)
E/AndroidRuntime(7118):     at java.util.HashMap$KeyIterator.next(HashMap.java:819) 
E/AndroidRuntime(7118):     at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1046)
E/AndroidRuntime(7118):     at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1048)
E/AndroidRuntime(7118):     at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1048)
E/AndroidRuntime(7118):     at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1048)
E/AndroidRuntime(7118):     at android.view.ViewRootImpl.handleDragEvent(ViewRootImpl.java:3471)
E/AndroidRuntime(7118):     at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2620)
E/AndroidRuntime(7118):     at android.os.Handler.dispatchMessage(Handler.java:99) 
E/AndroidRuntime(7118):     at android.os.Looper.loop(Looper.java:137) 
E/AndroidRuntime(7118):     at android.app.ActivityThread.main(ActivityThread.java:4575)
E/AndroidRuntime(7118):     at java.lang.reflect.Method.invokeNative(Native Method) 
E/AndroidRuntime(7118):     at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(7118):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
E/AndroidRuntime(7118):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
E/AndroidRuntime(7118):     at dalvik.system.NativeStart.main(NativeMethod)

为什么,以及如何解决它?

Why and how to fix it?

推荐答案

您可以试试这个

if (event.getAction() == DragEvent.ACTION_DRAG_ENDED) {
    final View droppedView = (View) event.getLocalState();
    droppedView.post(new Runnable(){
        @Override
        public void run() {
            droppedView.setVisibility(View.VISIBLE);
        }
    });
}

看起来像Android的自身试图访问视图状态的同时,你到底拖动。

Looks like Android itself trying to access View state at the same time as you end dragging.

修改

更多precise解释。通过设置 setVisibility(),你包括或不包括查看的意见Android的内部集合,应该响应拖动事件。拖动事件调度过程中,此集合使用,因此试图通过 setVisibility (换句话说,试图修改的拖动事件监听器),你会使 ConcurrentModificationException的

More precise explanation. By setting setVisibility(), you're including or excluding View from Android internal collection of views, that should respond to drag events. This collection is used during dispatch of drag events, and therefore by trying to setVisibility (in other words, trying to modify listeners of drag events) you're causing ConcurrentModificationException