Les modifications simultanées Exception : ajouter à une liste de tableaux
Le problème se produit à
Element element = it.next();
Et ce code qui contient cette ligne, qui est à l'intérieur d'un OnTouchEvent
for (Iterator<Element> it = mElements.iterator(); it.hasNext();){
Element element = it.next();
if(touchX > element.mX && touchX < element.mX + element.mBitmap.getWidth() && touchY > element.mY
&& touchY < element.mY + element.mBitmap.getHeight()) {
//irrelevant stuff..
if(element.cFlag){
mElements.add(new Element("crack",getResources(), (int)touchX,(int)touchY));
element.cFlag = false;
}
}
}
Tout cela est à l'intérieur de synchronized(mElements)
, où mElements
est un ArrayList<Element>
Quand je touche un Element
, il peut activer cFlag
, ce qui permettra de créer un autre Element
avec des propriétés différentes, qui tombent hors de l'écran et de détruire lui-même en moins d'une seconde. C'est ma façon de créer des effets de particules. Nous pouvons appeler cela une "particule" crack
, comme la Chaîne de caractère en paramètre dans le constructeur.
Tout cela fonctionne très bien jusqu'à ce que je ajouter un autre principal Element
. Maintenant, j'ai deux Elements
sur l'écran en même temps, et si je touche le plus récent Element
, il fonctionne très bien, et lance les particules.
Cependant, si je touche et activer cFlag
sur les anciens Element
, puis il me donne l'exception.
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): FATAL EXCEPTION: main
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): java.util.ConcurrentModificationException
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at com.Juggle2.Panel.onTouchEvent(Panel.java:823)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.view.View.dispatchTouchEvent(View.java:3766)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:863)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1767)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1119)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.app.Activity.dispatchTouchEvent(Activity.java:2086)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1751)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.view.ViewRoot.handleMessage(ViewRoot.java:1785)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.os.Handler.dispatchMessage(Handler.java:99)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.os.Looper.loop(Looper.java:123)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at android.app.ActivityThread.main(ActivityThread.java:4627)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at java.lang.reflect.Method.invokeNative(Native Method)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at java.lang.reflect.Method.invoke(Method.java:521)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:651)
07-28 15:36:59.815: ERROR/AndroidRuntime(4026): at dalvik.system.NativeStart.main(Native Method)
Comment puis-je faire ce travail?
- Double Possible de les modifications Simultanées exception
Vous devez vous connecter pour publier un commentaire.
ConcurrentModificationException se produit lorsque vous modifiez la liste (par l'ajout ou la suppression d'éléments) en parcourant une liste avec
Iterator
.Essayer
En outre, vous devriez envisager d'amélioration pour chaque boucle comme Jon l'a suggéré.
J'ai l'habitude d'utiliser quelque chose comme ceci:
rapide, propre et sans bug
une autre option est d'utiliser CopyOnWriteArrayList
Vous n'êtes pas autorisé à ajouter une entrée dans une collection, tandis que vous êtes une itération sur elle.
Une option consiste à créer une nouvelle
List<Element>
pour les nouvelles entrées pendant que vous êtes à parcourirmElements
, puis ajouter tous les nouveaux àmElement
par la suite (mElements.addAll(newElements)
). Bien sûr, cela signifie que vous n'avez pas exécuté le corps de la boucle pour ces nouveaux éléments - est-ce un problème?En même temps, je vous recommande de mettre à jour votre code pour utiliser la amélioré pour la boucle:
Indexé pour la boucle devrait également fonctionner.
ajout de la liste, dans ce cas, conduit à la CME, aucun montant de la
synchronized
vous permettra de l'éviter. Au lieu de cela, envisager de l'ajouter à l'aide de l'itérateur...Aussi je pense que c'est un peu glissante de l'état comme...
par souci de précision remarque que ci-dessus n'est pas garantie.
La documentation de l'API souligne que cette ...comportement ne peut pas être garanti car il est généralement impossible de faire tout dur garanties en présence de désynchroniser les modifications simultanées. Fail-fast opérations de jeter ConcurrentModificationException sur un base du meilleur effort...
Utilisation des Itérateurs résout également les problèmes de simultanéité, comme ceci:
Eh bien, j'ai essayé tous les aspects dans mon cas où j'ai une itération dans un adaptateur, une liste, mais en raison de frapper encore et encore, je m'a montré le message de l'exception levée .
J'ai essayé de Coulée de la liste de
mais elle aussi m'avaient envoyé une exception de CouldNotCastException,(et j'ai enfin réfléchi sur le fait que pourquoi utilisent-ils ou nous fournir une facality de casting).
J'ai même utilisé le soi-disant Bloc Synchronisé trop, mais même il n'a pas travaillé ou je pourrais aurait été de l'utiliser dans un mauvais sens.
Donc c'est quand j'ai enfin utilisé le #tous les temps# Technique de manipulation de l'exception
dans le bloc try catch, et cela a fonctionné
Afin de mettre votre code dans le