2011-02-21 2 views
4

Android 애플리케이션에서 Google API MapView를 사용하고 있으며지도를 스크롤하고 확대/축소 할 때이 오류가 자주 발생한다는 것을 발견했습니다. 그들은 아주 빨리 (지도를 사용하는 20 초) 일어나는 경향이 있으므로 문제가 될 것이라고 생각합니다. 아래는 내 stacktrace입니다. 나는 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) 

이것은 내 오버레이입니다. 그것에 투명도 (파일 크기 6KB)와 png 이미지 96x96을 표시하는 약 50 항목이 있습니다.

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