Итак, я портирую приложение, созданное для 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 (); функция. Я попытался удалить это и написать публичный метод, который переносит заполнение, которое я вызываю только после добавления всех элементов, но это просто не ощущается. Написание общедоступных методов для обёртывания частных, как правило, не очень хорошая идея.
Также это дает мне странное поведение, и все оверлеи получают одно и то же изображение, если я делаю это.
Так что же я делаю не так, или это просто факт, что Google Maps API на Android намного менее гибок, чем на iOS?