0

내 응용 프로그램은 Android 1.6에서 제대로 작동하지만 Android 2.2에서 실행할 때 일부 장소에서는 concurrentModificationException이 발생합니다. 며칠 동안 내 머리를 감싼 후에 이론을 제안했습니다. 1.6 이후 멀티 스레딩 (또는 비슷한)이 도입 된 것 같습니다. 이게 그럴 수 있니? 그렇다면 멀티 스레딩없이 응용 프로그램을 강제로 실행할 수있는 방법이 있습니까? 나는 목표를 1.6으로 설정하려했지만 운이 없다 .. 미리, 시간 내 주셔서 감사드립니다.1.6에서 2.2로 안드로이드를 업그레이드 할 때 예외가 발생합니다.

예외 : handleresult 코드와

04-05 11:47:12.812: ERROR/AndroidRuntime(5328): FATAL EXCEPTION: main 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { cmp=ntnu.client/com.google.android.maps.MapView (has extras) }} to activity {ntnu.client/ntnu.client.MapClient}: java.util.ConcurrentModificationException 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.app.ActivityThread.deliverResults(ActivityThread.java:3808) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.app.ActivityThread.handleSendResult(ActivityThread.java:3850) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.app.ActivityThread.access$2800(ActivityThread.java:136) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2209) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.os.Handler.dispatchMessage(Handler.java:99) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.os.Looper.loop(Looper.java:143) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.app.ActivityThread.main(ActivityThread.java:5068) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at java.lang.reflect.Method.invokeNative(Native Method) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at java.lang.reflect.Method.invoke(Method.java:521) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at dalvik.system.NativeStart.main(Native Method) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328): Caused by: java.util.ConcurrentModificationException 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at ntnu.client.MapClient.handleResult(MapClient.java:599) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at ntnu.client.MapClient.onActivityResult(MapClient.java:881) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.app.Activity.dispatchActivityResult(Activity.java:3988) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at android.app.ActivityThread.deliverResults(ActivityThread.java:3804) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  ... 11 more 

코드는 아래와 같습니다.

public synchronized void handleResult(boolean notify) 
    { 

     if(!citynodes.equals(null) && citynodes.size()>0) 
     { 
      noteBaloon.setVisibility(0x00000008); 

      Drawable drawable = this.getResources().getDrawable(R.drawable.up); 
      Context myContext = this; 

      itemizedoverlay = new CitynodeItemizedOverlay(drawable,myContext); 
      itemizedoverlay.setThumbsUp(BitmapFactory.decodeResource(
        getResources(), R.drawable.vote_yes3)); 

      itemizedoverlay.setThubmsDown(BitmapFactory.decodeResource(
        getResources(), R.drawable.vote_no3)); 
      itemizedoverlay.addObserver(this);  

      //itemizedoverlay.setDoAnimtation(true); 

      RecommendationNotificationOverlay overlay = new RecommendationNotificationOverlay(); 


      for (Recommendation n : citynodes) 
      { 

       CitynodeOverlayItem cn= n.getNode().getOverlayItem(); 
       Drawable marker = this.iconmanager.changeBackground(this.iconmanager.findIcon(n.getNode()),Integer.parseInt(n.getSystemRating()),n.isPersonalized()); 
       //marker.setAlpha(100); 
       marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight()); 

       ShapeDrawable l; 

       cn.setMarker(marker); 
       cn.setNode(n); 
       itemizedoverlay.addOverlay(cn); 

       LayoutInflater inflater = getLayoutInflater(); 
      } 



      for(Overlay i : getMapView().getOverlays()) 
      { 
       if((i instanceof ItemizedOverlay)) //|| (i instanceof RecommendationNotificationOverlay)) 
        this.mapView.getOverlays().remove(i); 
      } 



      for(Overlay i : getMapView().getOverlays()) 
      { 
       if((i instanceof RecommendationNotificationOverlay)) 
        this.mapView.getOverlays().remove(i); 
      } 
      List <Recommendation> proactive = new ArrayList<Recommendation>(); 

      for(Recommendation potpro : this.citynodes) 
      { 
       if(potpro.isProactive()) 
       { 
        proactive.add(potpro); 

       } 

      } 

      overlay.setNotifications(proactive); 

      mapOverlays.add(overlay); 



      mapOverlays.add(itemizedoverlay); 



      mapView.invalidate(); 

     } 

    } 

이 예외가 참조 부호는 제이기 루프 :

for(Overlay i : getMapView().getOverlays()) 

코드는 또한 (다른 액션 처리)이 라인에서 같은 예외 예외 :

if(!citynodes.equals(null) && citynodes.size()>0) 
+0

이 오류의 로그를 제공 할 수 있습니까? 1.6에서 2.2로 업그레이드하는 것이 문제가되지 않아야합니다. –

+0

오류가 thread.Did 때문이 아닙니다. 프로그램에서 오류가 발생 했습니까? –

+0

안드로이드는 항상 멀티 스레딩을 가지고 있었지만, 2.2에서는 JIT를 도입하여 속도가 약간 향상되었으며, 스레드가 이전에 행운을 가져다 줄 정도로 타이밍을 변경했을 수 있습니다. – Nick

답변

1

아, 문제 중 적어도 하나는 멀티 스레딩과 아무 상관 없다 : 당신이 반복하는 동안 당신은 컬렉션을 수정할 수 없습니다

for(Overlay i : getMapView().getOverlays()) 
{ 
    if (i instanceof ItemizedOverlay) 
     this.mapView.getOverlays().remove(i); 
} 

이 for-loop 스타일로 때로는 콜렉션 구현은 알아 차리지 못할 것이고, 그걸로 도망 갈 수는 있지만, 콜렉션의 구현이 이런 종류의 일을 잡을 수있는 안드로이드의 어느 시점에서 바뀔 수 있다고 생각합니다. 루핑하는 동안 항목을 제거하려면 Iterator을 가져와 Iteratorremove을 호출하여 루프를 수행해야합니다.

for(Iterator<Overlay> it=getMapView().getOverlays().iterator(); it.hasNext();) 
{ 
    Overlay i = it.next(); 
    if (i instanceof ItemizedOverlay) 
     it.remove(); 
} 

또는 그와 유사한 것.

+0

나는 이것을 일찍 발견 했어야합니다 - 'ConcurrentModificationException'은 일반적으로 이런 일이 일어 났음을 의미합니다. 두 스레드가 동시에 콜렉션을 수정하면 더 혼란스러운 예외가 발생하는 경향이 있습니다. – Nick

0

관심있는 오류 메시지의 부분입니다.

04-05 11:47:12.812: ERROR/AndroidRuntime(5328): Caused by: java.util.ConcurrentModificationException 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at ntnu.client.MapClient.handleResult(MapClient.java:599) 
04-05 11:47:12.812: ERROR/AndroidRuntime(5328):  at ntnu.client.MapClient.onActivityResult(MapClient.java:881) 

handleResult 메서드의 MapClient 클래스 줄 599에서 오류가 발생합니다. handleResult 메소드의 코드를 게시 할 수 있습니까?

두 개 이상의 스레드가 ArrayList를 동시에 수정하려고하므로 예외가 발생합니다.

+0

나는 그 코드를 보았다. 그것은 어디서나 med를 얻지 못했습니다.하지만 1.6에서 응용 프로그램이 작동하지만 2.2에서는 작동하지 않습니다. 2.2에서 매번 실패하고 1.6에서 결코 실패합니다. – pecka85

0

배열 내용을 수정하는 영역 주위에 랩 동기화 ([ArrayList]) {}. 그 방법은 스레드가 모두 배열의 내용을 변경 할 수 있습니다

+0

오늘 오후에 시도해 보겠습니다. 예외를 throw하는 메서드는 동기화되어 있습니다 (위의 코드 참조). – pecka85

+0

@ pecka85 -이 클래스의 인스턴스간에 공유되는 이러한 목록은 무엇입니까? 메서드에서'synchronized' 메서드는 해당 객체 인스턴스에서만 동기화되므로 동일한 데이터를 공유하는 경우 여전히 안전하지 않은 작업을 수행 할 수 있습니다. – Nick

+0

@Nick 해당 클래스 (활동)의 인스턴스는 하나뿐입니다. 그러나 꽤 비슷한 클래스 (액티비티)가 존재하지만이 다른 액티비티를 시작하지 않아도 주요 액티비티는 충돌합니다. – pecka85

관련 문제