问题
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)
}
}
}
And:
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?
回答1:
You can try this
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);
}
});
}
Looks like Android itself trying to access View state at the same time as you end dragging.
EDIT
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
回答2:
The best way is :
view.post(new Runnable() {
public void run() {
view.setVisibility(View.VISIBLE);
}
});
if we use:
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);
}
});
}
you will still get force close Null.pointer. ...
回答3:
Maybe this can help. here in the given link says: instead of DragEvent.ACTION_DRAG_ENDED use DragEvent.ACTION_DROP.
来源:https://stackoverflow.com/questions/10988671/java-util-concurrentmodificationexception-in-view-setvisibility