谷歌地图在安卓上非常缓慢,还是我使用方法不对?

3
所以我正在将几个月前为iOS制作的应用程序移植到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帧每秒或更少)。我认为奇怪的是每次调用add也会调用populate()函数。我尝试移除它并编写一个公共方法来包装populate,只有在添加所有项目之后才调用它,但感觉不正确。通常不推荐编写公共方法来包装私有方法。此外,如果这样做,会给我奇怪的行为,并且所有覆盖物都会得到相同的图像。

那么我做错了什么,还是Google Maps API在Android上比iOS灵活性差很多?

2个回答

3
我在这里取得了一些进展,可能对阅读此问题的一些人有用。 1.我现在已经将populate方法从add方法中移出,并包装在公共方法中,以便在填充完整个OverlayItems数组后仅调用一次。 此外,我尝试在未使用调试器的情况下运行应用程序,即仅在手机上运行应用程序,则可以平稳地运行。这不是我注意到调试器放慢操作速度的唯一时间,其速度降低了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();
}



}

不错的发现...将populate()移出addOverlay()并且在调试器断开连接时运行速度更快!我在Stackoverflow上阅读了6-7个其他相关的问题/答案,这是我第一次看到这个建议! - Tanner Perrien
我的性能问题似乎也与模拟器有关。该应用在手机上运行顺畅。 - Sand

0

添加

mapOverlays.clear();

紧接着

mapOverlays.add(itemizedOverlay);

加速了我的应用程序的性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接