Android MapView 内存使用率高的原因
我发现 GC 在我的地图活动中频繁释放内存,我无法找出原因,这种情况发生在地图开始构建标题时,即当我们滑动地图时。最终,由于内存越界异常,活动停止并强制退出。活动点存储在数组列表中的各个位置的地理点。随附的图像显示了这一点。
public class DetailMapTab extends MapActivity{
private MapView map=null;
private MyLocationOverlay me=null;
private SitesOverlay sites=null;
String placename;
int position;
String lat;
String lon;
ArrayList<HashMap<String, String>> mylist =new ArrayList<HashMap<String, String>>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapdetail);
//position -> is the selected record of the list
//mylist -> contains record sets to display like name , lat and lon of various location
placename=mylist.get(position).get("Name");
lat=mylist.get(position).get("Latitude");
lon=mylist.get(position).get("Longitude");
map=(MapView)findViewById(R.id.map);
map.getController().setCenter(getPoint(Double.valueOf(lat),Double.valueOf(lon)));
map.getController().setZoom(17);
map.setBuiltInZoomControls(true);
sites=new SitesOverlay();
map.getOverlays().add(sites);
me=new MyLocationOverlay(this, map);
map.getOverlays().add(me);
}//oncreate
@Override
public void onResume() {
super.onResume();
me.enableCompass();
}
@Override
public void onPause() {
super.onPause();
me.disableCompass();
}
@Override
protected boolean isRouteDisplayed() {
return(false);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_S) {
map.setSatellite(!map.isSatellite());
return(true);
}
else if (keyCode == KeyEvent.KEYCODE_Z) {
map.displayZoomControls(true);
return(true);
}
else if (keyCode == KeyEvent.KEYCODE_H) {
return(true);
}
return(super.onKeyDown(keyCode, event));
}
private GeoPoint getPoint(double lat, double lon) {
return(new GeoPoint((int)(lat*1000000.0),(int)(lon*1000000.0)));
}
private class SitesOverlay extends ItemizedOverlay<CustomItem> {
private List<CustomItem> items=new ArrayList<CustomItem>();
public SitesOverlay() {
super(null);
//show selected record geo-point with a new map pin1
items.add(new CustomItem(getPoint(Double.valueOf(lat),Double.valueOf(lon))," ", placename,getMarker(R.drawable.pin1)));
//show the geo-points names with pin2
for(int i=0;i<mylist.size();i++)
{
if(position!=i)
{
items.add(new CustomItem(getPoint(Double.valueOf(mylist.get(i).get("Latitude")),Double.valueOf(mylist.get(i).get("Longitude"))),"",mylist.get(i).get("Name"),getMarker(R.drawable.pin2)));
}
}
}
}
populate();
}
@Override
protected CustomItem createItem(int i) {
return(items.get(i));
}
@Override
public void draw(Canvas canvas, MapView mapView,boolean shadow) {
super.draw(canvas, mapView, shadow);
}
@Override
protected boolean onTap(int i) {
//OverlayItem item=getItem(i);
Toast.makeText(getApplicationContext(),items.get(i).getSnippet(),Toast.LENGTH_SHORT).show();
return(true);
}
@Override
public int size() {
return(items.size());
}
private Drawable getMarker(int resource) {
Drawable marker=getResources().getDrawable(resource);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),marker.getIntrinsicHeight());
boundCenterBottom(marker);
return(marker);
}
}
class CustomItem extends OverlayItem {
Drawable marker=null;
CustomItem(GeoPoint pt, String name, String snippet, Drawable marker) {
super(pt, name, snippet);
this.marker=marker;
}
@Override
public Drawable getMarker(int stateBitset) {
Drawable result= marker;
setState(result, stateBitset);
return(result);
}
}
public void onDestroy(){
super.onDestroy();
map=null;
me=null;
sites=null;
gr=null;
placename=null;
lat=null;
lon=null;
mylist =null;
System.gc();
}
}
我很高兴知道原因。当我滑动地图
11-11 15:39:55.072: DEBUG/dalvikvm(222): GC freed 439 objects / 83360 bytes in 106ms
11-11 15:39:56.052: DEBUG/dalvikvm(107): GC freed 3568 objects / 197464 bytes in 138ms
11-11 15:39:57.451: DEBUG/dalvikvm(222): GC freed 135 objects / 41456 bytes in 101ms
11-11 15:39:59.891: DEBUG/dalvikvm(222): GC freed 94 objects / 42112 bytes in 134ms
11-11 15:44:27.481: DEBUG/dalvikvm(104): GC freed 7472 objects / 406240 bytes in 140ms
时显示的日志
I found the GC kicks in frequently freeing memory in my map activity, I couldn't trace out the reason and this happens when map start constructing titles i.e when we slide the map. And eventually the activity stops to force quit due to memory out of bound exception. The activity points the geo points of various location stored in the arraylist. The image enclose show this.
public class DetailMapTab extends MapActivity{
private MapView map=null;
private MyLocationOverlay me=null;
private SitesOverlay sites=null;
String placename;
int position;
String lat;
String lon;
ArrayList<HashMap<String, String>> mylist =new ArrayList<HashMap<String, String>>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapdetail);
//position -> is the selected record of the list
//mylist -> contains record sets to display like name , lat and lon of various location
placename=mylist.get(position).get("Name");
lat=mylist.get(position).get("Latitude");
lon=mylist.get(position).get("Longitude");
map=(MapView)findViewById(R.id.map);
map.getController().setCenter(getPoint(Double.valueOf(lat),Double.valueOf(lon)));
map.getController().setZoom(17);
map.setBuiltInZoomControls(true);
sites=new SitesOverlay();
map.getOverlays().add(sites);
me=new MyLocationOverlay(this, map);
map.getOverlays().add(me);
}//oncreate
@Override
public void onResume() {
super.onResume();
me.enableCompass();
}
@Override
public void onPause() {
super.onPause();
me.disableCompass();
}
@Override
protected boolean isRouteDisplayed() {
return(false);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_S) {
map.setSatellite(!map.isSatellite());
return(true);
}
else if (keyCode == KeyEvent.KEYCODE_Z) {
map.displayZoomControls(true);
return(true);
}
else if (keyCode == KeyEvent.KEYCODE_H) {
return(true);
}
return(super.onKeyDown(keyCode, event));
}
private GeoPoint getPoint(double lat, double lon) {
return(new GeoPoint((int)(lat*1000000.0),(int)(lon*1000000.0)));
}
private class SitesOverlay extends ItemizedOverlay<CustomItem> {
private List<CustomItem> items=new ArrayList<CustomItem>();
public SitesOverlay() {
super(null);
//show selected record geo-point with a new map pin1
items.add(new CustomItem(getPoint(Double.valueOf(lat),Double.valueOf(lon))," ", placename,getMarker(R.drawable.pin1)));
//show the geo-points names with pin2
for(int i=0;i<mylist.size();i++)
{
if(position!=i)
{
items.add(new CustomItem(getPoint(Double.valueOf(mylist.get(i).get("Latitude")),Double.valueOf(mylist.get(i).get("Longitude"))),"",mylist.get(i).get("Name"),getMarker(R.drawable.pin2)));
}
}
}
}
populate();
}
@Override
protected CustomItem createItem(int i) {
return(items.get(i));
}
@Override
public void draw(Canvas canvas, MapView mapView,boolean shadow) {
super.draw(canvas, mapView, shadow);
}
@Override
protected boolean onTap(int i) {
//OverlayItem item=getItem(i);
Toast.makeText(getApplicationContext(),items.get(i).getSnippet(),Toast.LENGTH_SHORT).show();
return(true);
}
@Override
public int size() {
return(items.size());
}
private Drawable getMarker(int resource) {
Drawable marker=getResources().getDrawable(resource);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),marker.getIntrinsicHeight());
boundCenterBottom(marker);
return(marker);
}
}
class CustomItem extends OverlayItem {
Drawable marker=null;
CustomItem(GeoPoint pt, String name, String snippet, Drawable marker) {
super(pt, name, snippet);
this.marker=marker;
}
@Override
public Drawable getMarker(int stateBitset) {
Drawable result= marker;
setState(result, stateBitset);
return(result);
}
}
public void onDestroy(){
super.onDestroy();
map=null;
me=null;
sites=null;
gr=null;
placename=null;
lat=null;
lon=null;
mylist =null;
System.gc();
}
}
I am glad to know the reason. The log shown as when I slide the map
11-11 15:39:55.072: DEBUG/dalvikvm(222): GC freed 439 objects / 83360 bytes in 106ms
11-11 15:39:56.052: DEBUG/dalvikvm(107): GC freed 3568 objects / 197464 bytes in 138ms
11-11 15:39:57.451: DEBUG/dalvikvm(222): GC freed 135 objects / 41456 bytes in 101ms
11-11 15:39:59.891: DEBUG/dalvikvm(222): GC freed 94 objects / 42112 bytes in 134ms
11-11 15:44:27.481: DEBUG/dalvikvm(104): GC freed 7472 objects / 406240 bytes in 140ms
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
ItemizedOverlay
适用于适度数量的点。您的屏幕截图表明您可能有太多的点需要ItemizedOverlay
的实现来支持。我将首先禁用您的覆盖并查看您的 GC 问题是否消失。然后,引入少量点(例如 10 个)并观察事物的行为方式。如果一切正常,并且您通常会在地图上放置数百或数千个点,则您将需要编写自己的自定义
Overlay
类,该类更适合您的场景。另一方面,如果您的 GC 问题存在且几乎没有点,那么可能是其他问题(例如,将地图放在选项卡中)。
ItemizedOverlay
works well for modest numbers of points. Your screenshot suggests that you may have too many points forItemizedOverlay
's implementation to support.I would start by disabling your overlay and seeing if your GC problems go away. Then, introduce a small number of points (e.g., 10) and see how things behave. If everything is OK, and you ordinarily would be putting hundreds or thousands of points on the map, you will need to write your own custom
Overlay
class that is more optimized for your scenario.If, on the other hand, your GC problems exist with few to no points, then perhaps something else is the problem (e.g., having the map in a tab).