0

我的應用程序可以正常使用Android 1.6,但是當我在Android 2.2上運行它時,我在某些地方得到了concurrentModificationException。在我花了好幾天的時間來圍繞它之後,我提出了一個理論:我認爲自1.6以來已經引入了多線程(或類似的東西)。這可能嗎?如果是這樣,是否有辦法強制應用程序在沒有多線程的情況下運行?我試圖將目標設置爲1.6,但沒有運氣。提前,我想感謝您的時間。Android從1.6升級到2.2導致出現異常

例外:

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 

代碼與handleresult碼在下文提供。

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循環:

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

的代碼也會引發相同的異常在這條線(處理另一個動作):

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

你能提供這些錯誤的日誌嗎?因爲從1.6升級到2.2應該不成問題 – 2011-04-05 09:45:00

+0

錯誤不是由於thread.did導致程序中出現錯誤? – 2011-04-05 10:01:52

+0

Android始終有多線程,但2.2引入了JIT,它可以提高速度,並且可能會導致線程之間的時序發生改變,以前您很幸運,因此它沒有顯示出它的頭像。 – Nick 2011-04-05 11:59:54

回答

1

啊,你的問題至少有一個是無關的多線程:

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

不能修改的集合,而你遍歷用這種for循環的風格在它之上。有時收集實現不會注意到,你會擺脫它,但我懷疑集合的實現可能已經在Android中的某個時刻發生了變化,這可以捕捉到這類事情。如果要在循環中刪除項目,則需要獲得Iterator並使用它循環,請撥打Iterator調用remove

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

或者這樣的事情。

+0

我應該真的看準了這一點前面 - 'ConcurrentModificationException'通常意味着這樣的事情已經發生了。當兩個線程同時修改一個集合時,您往往會遇到更多令人困惑的異常。 – Nick 2011-04-06 09:30:28

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

我看過那段代碼。它沒有得到醫療任何地方..但那麼該應用程序是如何工作在1.6但不是2.2?它失敗在2.2每次,並且從不在1.6 .. – pecka85 2011-04-05 11:54:44

0

在修改Array內容的區域周圍包裝sychronized([ArrayList]){}。這樣的線程都能夠改變數組內容

+0

我想試試這個下午。拋出異常的方法是同步的(參見上面的代碼),在這種情況下不應該考慮到這一點嗎? – pecka85 2011-04-05 11:52:04

+0

@ pecka85 - 任何這些名單該類的實例之間共享的?方法上的'synchronized'只在該對象實例上同步,所以如果他們共享相同的數據,他們仍然可能會做不安全的事情。 – Nick 2011-04-05 11:56:09

+0

@Nick該類只有一個實例(活動)。然而,一個非常相似的類(活動)存在,但即使沒有這個開始其他活動,主要活動崩潰.. – pecka85 2011-04-05 13:42:14