所以我在几个月前将我为iOS制作的App移植到Android上。这个应用程序有一个数百(341)点的数据库,可以在地图上显示。在iOS上执行此操作时,我将这些点添加到地图时没有遇到任何性能问题。如果用户缩小以便所有可以立即看到的点你可以注意到一些减速但没什么大不了的话。另一方面,在Android上,这种情况非常缓慢到了冻结的程度。 AVD比手机(HTC Hero)慢。
我想指出我是java的新手,但我有C / C ++ / OBJ-C的经验。 我已经用我的代码略微改编了一下并使用了一些简单的性能测量结果,并对我的代码得出了一些令人惊讶的结论。
这是我的MapActivity中的功能,用于向我的地图添加叠加层我已经留下了一些注释掉的代码,我将在那里解释。
private void addOverlaysToMapFromManagedInterestPoints() {
this.mapOverlays = myMap.getOverlays();
GeoPoint point;
OverlayItem overlayitem;
for( managed_interest_point mip : managedObjectManager.interestPoints )
{
TypeOfPoint type = getEnumForTypeOfPoint(mip.ZTYPEOFPOINT);
if(type!=null)
{
switch (type) {
case kAnimalHospital:
point = new GeoPoint(degreesToMicrodegreesConversion(mip.ZLATITUDE),degreesToMicrodegreesConversion(mip.ZLONGITUDE));
overlayitem = new OverlayItem(point, mip.ZTITLE, mip.ZSUBTITLE);
//this.animalHospitalOverlay.addOverlay(overlayitem);
AnnotationsOverlay testOverlay = new AnnotationsOverlay(this.animalHospitalPin,this);
testOverlay.addOverlay(overlayitem);
Log.d("MainActivity","added animalHospital");
break;
case kStore:
point = new GeoPoint(degreesToMicrodegreesConversion(mip.ZLATITUDE),degreesToMicrodegreesConversion(mip.ZLONGITUDE));
overlayitem = new OverlayItem(point, mip.ZTITLE, mip.ZSUBTITLE);
//this.storesOverlay.addOverlay(overlayitem);
AnnotationsOverlay testOverlay2 = new AnnotationsOverlay(storePin,this);
testOverlay2.addOverlay(overlayitem);
this.mapOverlays.add(testOverlay2);
Log.d("MainActivity","added Store point");
break;
case kVeterinary:
point = new GeoPoint(degreesToMicrodegreesConversion(mip.ZLATITUDE),degreesToMicrodegreesConversion(mip.ZLONGITUDE));
overlayitem = new OverlayItem(point, mip.ZTITLE, mip.ZSUBTITLE);
//this.storesOverlay.addOverlay(overlayitem);
AnnotationsOverlay testOverlay3 = new AnnotationsOverlay(this.veterinaryPin,this);
testOverlay3.addOverlay(overlayitem);
this.mapOverlays.add(testOverlay3);
Log.d("MainActivity","added veterinary point");
break;
default:
Log.d("MainActivity", "unknown enum");
break;
}//end switch
}//end if
}//end foreach
//this.mapOverlays.add(this.storesOverlay);
//this.mapOverlays.add(this.veterinariesOverlay);
//this.mapOverlays.add(this.animalHospitalOverlay);
Log.d("MainActivity","end of foreach in add overlays to map ");
}
这是AnnotationsOverlay的代码,我是ItemizedOverlay的子类。
public class AnnotationsOverlay extends ItemizedOverlay {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
Context mContext;
public AnnotationsOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
public AnnotationsOverlay(Drawable defaultMarker,Context context)
{
super(boundCenterBottom(defaultMarker));
mContext=context;
}
@Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
@Override
public int size() {
return mOverlays.size();
}
//show calloutAssesory view tapped för oss iPhöne människor
@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;
}
public void addOverlay(OverlayItem overlay)
{
mOverlays.add(overlay);
populate();
}
}
我的第一直觉是在循环中分配AnnotationsOverlay会是一件坏事,因为它似乎可以作为某种类型的集合,你应该添加多个项目。
这个假设被证明是错误的,因为每次后续调用add()的时间越来越长。我把这个分配放在循环中,现在这个函数在可接受的时间内执行。所有的点都显示在地图上,但它超级慢(2 fps可能更少)。我认为每次调用add都会调用populate()是很奇怪的。功能。我已经尝试删除它并编写一个公共方法,包装填充,我只在添加所有项目后调用,但这只是感觉不太严格。编写公共方法来包装私有方法通常不是一个好主意。 此外,它给了我奇怪的行为,如果我这样做,所有叠加层都会获得相同的图像。
那么我做错了什么,或者只是因为Android上的Google Maps API比iOS上的灵活性差得多?
答案 0 :(得分:3)
我在这里取得了一些进展,这对你们中的一些人来说可能有用。 1.我现在已经将我的populate方法从我的add方法中移出并将其包装在public方法中,以便在填充整个OverlayItem数组后我只能调用它一次。 此外,我尝试在没有调试器的情况下运行应用程序,即只需在手机上运行应用程序即可顺利运行。这不是我注意到调试器减慢10-20或更多因素的唯一时间。我在过去遇到过类似的问题,在调试模式下运行会使一些操作在极短的时间内变慢。
新代码如下所示:
private void addOverlaysToMapFromManagedInterestPoints() {
this.mapOverlays = myMap.getOverlays();
GeoPoint point;
OverlayItem overlayitem;
for( managed_interest_point mip : managedObjectManager.interestPoints )
{
if(mip==null)
{
Log.d("MainActivity","this should not happen!");
}
TypeOfPoint type = getEnumForTypeOfPoint(mip.ZTYPEOFPOINT);
if(type!=null)
{
switch (type) {
case kAnimalHospital:
point = new GeoPoint(degreesToMicrodegreesConversion(mip.ZLATITUDE),degreesToMicrodegreesConversion(mip.ZLONGITUDE));
overlayitem = new OverlayItem(point, mip.ZTITLE, mip.ZSUBTITLE);
this.animalHospitalOverlay.addOverlay(overlayitem);
Log.d("MainActivity","added animalHospital");
break;
case kStore:
point = new GeoPoint(degreesToMicrodegreesConversion(mip.ZLATITUDE),degreesToMicrodegreesConversion(mip.ZLONGITUDE));
overlayitem = new OverlayItem(point, mip.ZTITLE, mip.ZSUBTITLE);
this.storesOverlay.addOverlay(overlayitem);
Log.d("MainActivity","added Store point");
break;
case kVeterinary:
point = new GeoPoint(degreesToMicrodegreesConversion(mip.ZLATITUDE),degreesToMicrodegreesConversion(mip.ZLONGITUDE));
overlayitem = new OverlayItem(point, mip.ZTITLE, mip.ZSUBTITLE);
this.veterinariesOverlay.addOverlay(overlayitem);
Log.d("MainActivity","added veterinary point");
break;
default:
Log.d("MainActivity", "unknown enum");
break;
}//end switch
}//end if
}//end foreach
this.storesOverlay.callToPopulate();
this.veterinariesOverlay.callToPopulate();
this.animalHospitalOverlay.callToPopulate();
this.mapOverlays.add(this.storesOverlay);
this.mapOverlays.add(this.veterinariesOverlay);
this.mapOverlays.add(this.animalHospitalOverlay);
Log.d("MainActivity","end of foreach in add overlays to map ");
}
public class AnnotationsOverlay extends ItemizedOverlay {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
Context mContext;
public AnnotationsOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
public AnnotationsOverlay(Drawable defaultMarker,Context context)
{
super(boundCenterBottom(defaultMarker));
mContext=context;
}
@Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
@Override
public int size() {
return mOverlays.size();
}
//show calloutAssesory view tapped för oss iPhöne människor
@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;
}
public void addOverlay(OverlayItem overlay)
{
mOverlays.add(overlay);
//populate();
}
public void callToPopulate()
{
populate();
}
}
答案 1 :(得分:0)
添加
mapOverlays.clear();
直接
mapOverlays.add(itemizedOverlay);
加快了我的应用程序的性能。