Android:Google地图在缩放时崩溃(超过1500个图标)

时间:2011-12-16 09:38:43

标签: android google-maps out-of-memory itemizedoverlay overlayitem

我想用Google API显示许多图标(超过2,000个图标)。我基于此tuto创建了一个简单的活动。

访问地图时显示没有任何问题图标。但是,当我放大/缩小几次时,java.lang.OutOfMemoryError:

12-16 08:48:29.415: E/dalvikvm-heap(606): 680640-byte external allocation too large for this process.
12-16 08:48:29.415: E/GraphicsJNI(606): VM won't let us allocate 680640 bytes
12-16 08:48:29.415: D/AndroidRuntime(606): Shutting down VM
12-16 08:48:29.415: W/dalvikvm(606): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
12-16 08:48:29.425: E/AndroidRuntime(606): FATAL EXCEPTION: main
12-16 08:48:29.425: E/AndroidRuntime(606): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.graphics.Bitmap.nativeCreate(Native Method)
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:151)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:140)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.google.android.maps.MapView.doZoom(MapView.java:1478)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.google.android.maps.MapView.doZoom(MapView.java:1487)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.google.android.maps.MapView$4.onClick(MapView.java:1381)
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.view.View.performClick(View.java:2408)
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.view.View$PerformClick.run(View.java:8816)
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.os.Handler.handleCallback(Handler.java:587)
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.os.Handler.dispatchMessage(Handler.java:92)
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.os.Looper.loop(Looper.java:123)
12-16 08:48:29.425: E/AndroidRuntime(606):  at android.app.ActivityThread.main(ActivityThread.java:4627)
12-16 08:48:29.425: E/AndroidRuntime(606):  at java.lang.reflect.Method.invokeNative(Native Method)
12-16 08:48:29.425: E/AndroidRuntime(606):  at java.lang.reflect.Method.invoke(Method.java:521)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-16 08:48:29.425: E/AndroidRuntime(606):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-16 08:48:29.425: E/AndroidRuntime(606):  at dalvik.system.NativeStart.main(Native Method)

这是我的活动方法:

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);    
    requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);     
    setContentView(R.layout.google_map);       

    Bundle bundle = getIntent().getExtras();

    //MAP    
    mapView = (MapView) findViewById(R.id.mapView);

    //zoom設定
    LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom);  
    View zoomView = mapView.getZoomControls(); 

    zoomLayout.addView(zoomView, 
       new LinearLayout.LayoutParams(
           LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); 
    mapView.displayZoomControls(true);

    //controller
    mc = mapView.getController();

    double[] adresse = (double[]) bundle.getDoubleArray(Site.LATTITUDE);     
    p = new GeoPoint((int) (adresse[0] * 1E6), (int) (adresse[1] * 1E6));

    mc.animateTo(p);
    mc.setZoom(18); 
    mapView.invalidate();

    List<Overlay> listOfOverlays = mapView.getOverlays();
    listOfOverlays.clear();

    try {

        //get datas from previous activiity
        List<SiteGoogle> sitesList = bundle.getParcelableArrayList(Site.JSON_ARRAY);

        //display message
        Toast.makeText(getBaseContext(), getResources().getString(R.string.map_toad), Toast.LENGTH_LONG).show();

        List<Overlay> mapOverlays = mapView.getOverlays();
        mapOverlays.clear();

        for(SiteGoogle site: sitesList) {  

            //set icon
            Drawable drawable = this.getResources().getDrawable(R.drawable.icon01);

            //icon setting
            MapItemizedOverlay itemizedoverlay = new MapItemizedOverlay(drawable,this);    

            //geoPoint
            GeoPoint point = new GeoPoint((int) (site.getLatitude() * 1E6), (int) (site.getLongitude() * 1E6));

            //item
            OverlayItem overlayitem = new OverlayItem(point, String.valueOf(site.getId()), null);

            itemizedoverlay.addOverlay(overlayitem);

            //add to map
            mapOverlays.add(itemizedoverlay);

        }

    } catch(Exception e) {
        Log.e(TAG,e.getMessage());
    }

我的MapItemizedOverlay类:

@SuppressWarnings("rawtypes")
public class MapItemizedOverlay extends ItemizedOverlay {

    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    private Context mContext;

    public MapItemizedOverlay(Drawable defaultMarker, Context context) {
        super(boundCenterBottom(defaultMarker));
        mContext = context;
    }

    public void addOverlay(OverlayItem overlay) {
        mOverlays.add(overlay);
        populate();
    }

    @Override
    protected OverlayItem createItem(int i) {
        return mOverlays.get(i);
    }

    @Override
    public int size() {
        return mOverlays.size();
    }

    @Override
    protected boolean onTap(int index){

        OverlayItem item = mOverlays.get(index);

        Intent intent = new Intent(mContext, SiteDetailsActivity.class);
        intent.putExtra(Site.ID, Integer.parseInt(item.getTitle()));        
        mContext.startActivity(intent);

        return true;
    }

我不知道我能做些什么才能让它变得更快而不会崩溃。我应该使用画布还是缓存?我没有想法。

2 个答案:

答案 0 :(得分:0)

我不确定它会有所帮助,但您在Overlay的循环中每sitesitesList添加到地图中:

for(SiteGoogle site: sitesList){  

        //set icon
        Drawable drawable = this.getResources().getDrawable(R.drawable.icon01);


       //icon setting
       MapItemizedOverlay itemizedoverlay = new MapItemizedOverlay(drawable,this);    

       //geoPoint
       GeoPoint point = new GeoPoint((int) (site.getLatitude() * 1E6), (int) (site.getLongitude() * 1E6));

       //item
       OverlayItem overlayitem = new OverlayItem(point, String.valueOf(site.getId()), null);

       itemizedoverlay.addOverlay(overlayitem);

       //add to map
       mapOverlays.add(itemizedoverlay);

        }

所以你最终得到2000 Overlays和2000 Drawables,这并不好。

可以更有效地使用ItemizedOverlay

Drawable drawable = this.getResources().getDrawable(R.drawable.icon01);
MapItemizedOverlay itemizedoverlay = new MapItemizedOverlay(drawable,this);

for(SiteGoogle site: sitesList) {  
    GeoPoint point = new GeoPoint((int) (site.getLatitude() * 1E6), (int) (site.getLongitude() * 1E6));
    OverlayItem overlayitem = new OverlayItem(point, String.valueOf(site.getId()), null);

    itemizedoverlay.addOverlay(overlayitem);
}
mapOverlays.add(itemizedoverlay);

答案 1 :(得分:0)

正如Darth Beleg所说,我把“mapOverlays.add(itemizedoverlay)”放在循环之外,我改变了“mapView.invalidate()”的位置。但没有出现。

这个项目的死线是在几天之内,我今天必须解决这个问题。如果有人可以帮助我,我会很高兴。

活动的新代码:

  public void onCreate(Bundle savedInstanceState) {

           super.onCreate(savedInstanceState);     
           requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);      
           setContentView(R.layout.google_map);    

           //SearchActivity parameters
           Bundle bundle = getIntent().getExtras();

           //MAP     
           mapView = (MapView) findViewById(R.id.mapView);

           //zoom設定
           LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom);  
           View zoomView = mapView.getZoomControls(); 

           zoomLayout.addView(zoomView, 
               new LinearLayout.LayoutParams(
                   LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); 
           mapView.displayZoomControls(true);

          mc = mapView.getController();

          double[] adresse = (double[]) bundle.getDoubleArray(Site.LATTITUDE);     
           p = new GeoPoint((int) (adresse[0] * 1E6), (int) (adresse[1] * 1E6));

           mc.animateTo(p);
           mc.setZoom(18); 


           //get current position
           List<Overlay> listOfOverlays = mapView.getOverlays();
           listOfOverlays.clear();

           try{

               //get icon position informations
               List<SiteGoogle> sitesList = bundle.getParcelableArrayList(Site.JSON_ARRAY);

                //message diplay
               Toast.makeText(getBaseContext(), getResources().getString(R.string.map_toad), Toast.LENGTH_LONG).show();

               List<Overlay> mapOverlays = mapView.getOverlays();
               mapOverlays.clear();

               MapItemizedOverlay itemizedoverlay = null;

               for(SiteGoogle site: sitesList){   

                   //set the icon
                   Drawable drawable;

                   switch (site.getCategory()){
                       case 1:
                           drawable = this.getResources().getDrawable(R.drawable.icon01);
                           break;
                       case 2:
                           drawable = this.getResources().getDrawable(R.drawable.icon02);
                           break;
                       case 3:
                           drawable = this.getResources().getDrawable(R.drawable.icon03);
                           break;
                       case 4:
                           drawable = this.getResources().getDrawable(R.drawable.icon04);
                           break;
                       case 5:
                           drawable = this.getResources().getDrawable(R.drawable.icon05);
                           break;
                       case 6:
                           drawable = this.getResources().getDrawable(R.drawable.icon06);
                           break;
                       case 7:
                           drawable = this.getResources().getDrawable(R.drawable.icon07);
                           break;
                       case 0:
                           drawable = this.getResources().getDrawable(R.drawable.icon00);
                           break;
                       default:
                           drawable = this.getResources().getDrawable(R.drawable.icon01);
                           break;
                   }


                itemizedoverlay = new MapItemizedOverlay(drawable,this);

               //geoPoint
               GeoPoint point = new GeoPoint((int) (site.getLatitude() * 1E6), (int) (site.getLongitude() * 1E6));

               //item
               OverlayItem overlayitem = new OverlayItem(point, String.valueOf(site.getId()), null);

               itemizedoverlay.addOverlay(overlayitem);

                }

               //add to map
               mapOverlays.add(itemizedoverlay);

               mapView.invalidate();

           }catch(Exception e){
              Log.e(TAG,e.getMessage());
          }

}