2011-02-21 13 views
4

私はAndroidアプリケーションでGoogle API MapViewを使用しています。地図をスクロールしてズームすると、このエラーが発生することがよくあります。彼らはかなり早く(マップの使用の20秒)起こる傾向があるので、私はそれが問題になると信じています。以下は私のスタックトレースです。私は24MBのメモリの余裕があるHTC Desireで開発しています。Google API MapView OutOfMemoryErrorの問題

私はこれらのエラーの頻度を減らすために何かできるのですか?

java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
    at android.graphics.Bitmap.nativeCreate(Native Method) 
    at android.graphics.Bitmap.createBitmap(Bitmap.java:574) 
    at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444) 
    at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:151) 
    at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:140) 
    at com.google.android.maps.MapView.doZoom(MapView.java:1478) 
    at com.google.android.maps.MapView.doZoom(MapView.java:1487) 
    at com.google.android.maps.MapView$6.onZoom(MapView.java:1442) 
    at android.widget.ZoomButtonsController$3.onClick(ZoomButtonsController.java:268) 
    at android.view.View.performClick(View.java:2408) 
    at android.view.View$PerformClick.run(View.java:8817) 
    at android.os.Handler.handleCallback(Handler.java:587) 
    at android.os.Handler.dispatchMessage(Handler.java:92) 
    at android.os.Looper.loop(Looper.java:144) 
    at android.app.ActivityThread.main(ActivityThread.java:4937) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:521) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
    at dalvik.system.NativeStart.main(Native Method) 


debug.heap native: allocated 10.63MB of 11.01MB (385.98KB free) 
debug.memory: allocated: 17.95MB of 24.00MB (13.50MB free) 

これは私のオーバーレイです。私は約50の項目をいくつかの透明性(ファイルサイズで6キロバイト)と96x96の画像を表示している。

public class StationItemizedOverlay extends ItemizedOverlay<OverlayItem> 
{ 
    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>(); 
    private ArrayList<Location> locations = new ArrayList<Location>(); 


    private Context mContext; 

    public StationItemizedOverlay(Drawable defaultMarker, Context context) 
    { 
     super(boundCenterBottom(defaultMarker)); 
     this.mContext = context; 
    } 

    /** 
    * Add a range of locations to this overlay 
    * 
    * @param locations The locations to add 
    */ 
    public void addRange(List<Location> locations) 
    { 
     for (Location l : locations) 
     { 
      addOne(l); 
     } 
     populate(); 
    } 

    /** 
    * Add a location to this overlay 
    * 
    * @param location The location 
    */ 
    public void add(Location location) 
    { 
     addOne(location); 
     populate(); 
    } 

    /** 
    * Remove a location from this overlay 
    * @param location The location to remove 
    */ 
    public void remove(Location location) 
    { 
     int position = locations.indexOf(location); 

     if (position >= 0) 
     { 
      mOverlays.remove(position); 
      locations.remove(position); 
      populate(); 
     } 
    } 

    private void addOne(Location location) 
    { 
     locations.add(location); 
     int lat = location.getMicroLatitude(); 
     int lon = location.getMicroLongitude(); 
     GeoPoint point = new GeoPoint(lat, lon); 
     OverlayItem item = new OverlayItem(point, location.getRealName(), location.getRealName()); 
     mOverlays.add(item); 
    } 

    @Override 
    protected boolean onTap(int index) 
    { 
     OverlayItem item = mOverlays.get(index); 
     AlertDialog.Builder dialog = new AlertDialog.Builder(mContext); 
     dialog.setTitle(item.getTitle()); 
     dialog.setMessage(item.getSnippet()); 
     dialog.show(); 
     return true; 
    } 

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

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

} 

これは、あなたが使用している必要がありオーバーレイの数が多いと、大きいサイズと無描画可能reusablityのイメージを持つ単一のオーバーレイによるものでなければならない私のMapActivityClass

public class StationFinder extends MapActivity 
{ 
    IUIInterface dataInterface = UIInterfaceFactory.getInterface(); 

    MapView mapView; 

    List<Overlay> mapOverlays; 
    Drawable drawable; 
    StationItemizedOverlay trainItemizedOverlay; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.ui_station_finder); 

     mapView = (MapView) findViewById(R.id.stationFinderUI_mapview); 
     mapView.setBuiltInZoomControls(true); 

     mapOverlays = mapView.getOverlays(); 
     drawable = getResources().getDrawable(R.drawable.dash_train_btn_default); 
     trainItemizedOverlay = new StationItemizedOverlay(drawable, this); 

     myMapController = mapView.getController(); 
     myMapController.setZoom(8); // zoom level selected from google map .com 

     // center this location on northern ireland 
     centerLocation(Settings.getNorthernIrelandCenter().getGeoPoint()); 

     mapOverlays.add(trainItemizedOverlay); 

     // add data to the adapters only whenever the data is loaded 
     if (!dataInterface.isDataLoaded()) 
     { 
      // data is not loaded 
      // so make a listener for the data loaded event 
      dataLoadedListener = new IEventListener() 
      { 
       public void action(Object optionalData) 
       { 
        // the event has been triggered 
        // register this function to run in the UI thread of the application 
        runOnUiThread(new Runnable() 
        { 
         public void run() 
         { 
          dataLoaded(); 
         } 
        }); 
       } 
      }; 
      // register the listener for data loaded events 
      dataInterface.registerDataLoaded(dataLoadedListener); 
      // call the data loaded function now incase the data has since been loaded by 
      // the application between registering for the event 
      if (dataInterface.isDataLoaded()) 
      { 
       dataLoaded(); 
      } 
     } 
     else 
     { 
      // data already loaded so run immediately 
      dataLoaded(); 
     } 



    } 

    IEventListener dataLoadedListener = null; 
    boolean isDataLoaded = false; 

    private void dataLoaded() 
    { 
     // make sure this function is only called once 
     if (isDataLoaded) 
      return; 
     isDataLoaded = true; 

     // IMPORTANT STUFF GOES HERE 



     trainItemizedOverlay.addRange(dataInterface.getAllLocations()); 


     // clean up the data load listener 
     if (dataLoadedListener != null) 
     { 
      dataInterface.removeDataLoaded(dataLoadedListener); 
      dataLoadedListener = null; 
     } 
    } 

    private MapController myMapController; 

    private void centerLocation(GeoPoint center) 
    { 
     myMapController.animateTo(center); 

     myMapController.setCenter(center); 
    }; 


    @Override 
    protected boolean isRouteDisplayed() 
    { 
     return false; 
    } 
+0

ありがとうございました!あなたの例の前に、私はオーバーレイが複数の場所を指し示すことがあるとは決して捉えませんでした!ああ、私は時々とても悪いです! :) – Snicolas

答えて

1

奇妙なことに、この問題は停止しました。なぜ私が推測しているのは、他のメモリの最適化によって、地図の描画に使用できるより大きなメモリブロックが作れたということです。

0

です。ここにコードを投稿して見せてもらえればもっとうまく答えることができます...

+0

私は自分のコードを投稿しました – Kurru

+0

http://blog.pocketjourney.com/2008/03/19/tutorial-2-mapview-google-map-hit-testing-for-display-of-popup-windows/ add 6kbイメージの50以上のオーバーレイをこのマップチュートリアルに追加します。それがそこで動作する場合、あなたのコードをデバッグし、そうでなければ画像サイズで作業してください... – Javanator