安卓地图异步加载覆盖物项

4

我有一个地图视图,上面有成千上万个项目需要加载。显然,在创建视图时无法全部加载。

我猜我必须根据当前显示的内容异步加载它们。

如何仅加载屏幕上显示的地图部分中的项目?

1个回答

8

使用AsyncTask将每个屏幕的单独图层加载。利用MapView api获取当前可见地图的纬度/经度。在后端发送纬度/经度边界框以获取所需的项目。大致从记忆中看,代码如下:

public class LoadMapItems extends AsyncTask<Integer,Integer,List<ItemizedOverlay>> {
   private MapView view;

   public LoadMapItems( MapView view ) {
      this.view = view;
   }

   public List<ItemizedOverlay> doInBackground( Integer... params ) {
      int left = params[0];
      int top = params[1];
      int right = params[2];
      int bottom = params[3];

      return convertToItemizedOverlay( someService.loadSomething( left, top, right, bottom ) );
   } 

   private List<ItemizedOverlay> convertToItemizedOverlay( List<SomeObject> objects ) {
      // ... fill this out to convert your back end object to overlay items
   }

   public void onPostExecute(List<ItemizedOverlay> items) {
      List<Overlay> mapOverlays = mapView.getOverlays();
      for( ItemizedOverlay item : items ) {
         mapOverlays.add( item );
      }
   }
}

// somewhere else in your code you do this:

GeoPoint center = someMap.getMapCenter();
new LoadMapItems( someMap ).execute( 
      center.getLongitude() - someMap.getLongitudeSpan() / 2,
      center.getLatitude() - someMap.getLatitudeSpan() / 2,
      center.getLongitude() + someMap.getLongitudeSpan() / 2,
      center.getLatitude() + someMap.getLatitudeSpan() / 2);

谢谢!这非常有帮助。但是我该如何处理当前可见地图的更改? - Matteo
您的MapView将在有人移动它时分派事件。在该事件处理程序中,您将使用此AsyncTask从后端服务加载数据。我会让它工作,然后一旦它工作了,我会考虑将这些负载缓存在数据结构中,可能是Map<Bound Box,List<ItemizedOverlay>>。这变得有点棘手,但它可以使速度更快。然后,当用户拖动地图以查看是否已加载该瓷砖时,您将检查该数据结构... - chubbsondubs
事实上,你可能会发现将叠加层分配给固定的网格单元并加载那些与你的MapView当前的纬度/经度跨度相交的网格单元更容易,就像我所演示的那样。这样可以更容易地缓存固定的网格段。你可能会加载存在于可视区域之外的要素,但它会很小。加载的网格单元数量的最大值将为4。此外,它更容易在后端进行优化,因为你的数据库可以基于一个固定的键进行索引。你只需要将纬度/经度转换为网格单元号,并加载分配给该网格单元号的要素即可。 - chubbsondubs

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