1

我有一个应用程序,用户可以在其中加载谷歌地图上的图像。这是为 2.3 开发的,所以有一个 MapActivity、一个 MapView 和我的自定义 Overlay 类来显示图像。在覆盖类绘制方法中,我每次都重新计算一个矩阵,因此图像得到正确的大小和位置。我还有一个校准模式,用户可以通过拖动参考点来调整图像。

我将向应用程序添加一些功能,并且我想从一些更新开始,例如使用片段。用 MapFragment 替换 MapActivity 会带来一些问题,因为似乎不支持您可以自己实现绘图的叠加层。看来我将不得不使用 GroundOverlays 或 TileOverlay。(如果我错了,请纠正我。)

这些似乎都不支持在添加叠加层后对其进行任何修改,因此图像的校准将不起作用。我对这部分的计划是在 MapFragment 顶部放置一个普通的 ImageView 用于校准模式。(这将隐藏所有标记,但这在校准期间并不重要。)为此,我需要两件事: * 接收影响校准点的所有触摸事件并转发其余的以允许正常缩放等 * 随时检测位置/旋转/缩放级别发生变化,因此我可以调整图像。问题#1:我可以期待任何重大问题吗?

然后我必须决定是否首选 GroundOverlays 或 TileOverlay。

GroundOverlay:这似乎需要最少的工作,因为它仍然会加载整个图像。我还认为它会自动处理屏幕方向变化等事情。问题 #2:GroundOverlay 能否很好地处理大图像(最大 2000*2000 像素)?是否有任何涉及图像的复制?由于图像太大,我无法在内存中复制一份以上。

TileOverlay:从某种意义上说,这似乎是一个更专业的解决方案,因为它只使用实际需要的部分,并且我稍后可以介绍对同时使用多个地图图像源的支持。我可能必须提前生成图块并为每个图块保存一个单独的文件,将其保存在内存中并按需创建图块可能会占用大量内存。(或者也许我可以创建一个单独的 tile 服务,但这似乎有点脏。) 问题 #3:是否可以控制 tile 缓存将使用多少内存?是否适用通常的限制?我不想仅仅因为缓存占用了我允许使用的大部分内存而在应用程序的其他地方耗尽内存。问题 #4:文档说“请注意,与其他叠加层不同,如果重新创建地图,因此这意味着必须再次读取文件,从而导致明显的加载延迟。有什么好办法解决这个问题吗?问题5:当getTile被调用,我返回null(因为tile保存在一个文件中,我不想在读取的时候阻塞ui线程),需要多长时间才能再次请求它?(似乎没有办法手动加载单个图块。) 问题 6:如何确定一个图块图像的良好图像分辨率(关于性能和质量)?因此这意味着必须再次读取文件,从而导致明显的加载延迟。有什么好办法解决这个问题吗?问题5:当getTile被调用,我返回null(因为tile保存在一个文件中,我不想在读取的时候阻塞ui线程),需要多长时间才能再次请求它?(似乎没有办法手动加载单个图块。) 问题 6:如何确定一个图块图像的良好图像分辨率(关于性能和质量)?

4

1 回答 1

6

很多问题。我会尝试解决一些问题。

  1. 通常,请注意 Maps API v2 比 v1 宽松得多。这是一件好事。v2 有许多 v1 没有的内置函数和优化,并且通过限制性 API 迫使您使用它的优化。

  2. 例如,如果您使用 GroundOverlay 显示图像[假设您不需要旋转或扭曲它],您只需指定它的纬度/经度边界,Maps v2 将为您拉伸图像。2000x2000 将是 2000x2000x4 字节,因此内存中有 16MBytes。但是 GroundOverlayOptions 使用 BitmapDescriptor,所以它可能永远不会将图像完全加载到内存中。我对 GroundOverlay 不是很熟悉。

    另一种选择是在第一次加载图像时将图像切割成平铺并将它们保存在本地存储中,然后与 TileOverlay 一起使用非常简单。您不能直接从 2kx2k 图像中合理地读取图块,因为它会涉及到全部读取(如果压缩,我猜是这样)。如果您需要显示图像的修改版本,请记住,在确保它是可变的之后,您只需要在位图上创建一个画布。

  3. 我更熟悉我经常使用的 TileOverlay。切片缓存对我来说看起来很公平,我已经加载了大量的 256x256 切片并且总是保持在 13M 和 20M 之间的堆。我认为它使用与谷歌地图图块相同的方法,在本地存储内存中缓存一些但不会太多,并且根本不缓存未显示的内存图块。您可以在填充时看到正在重新加载图块。

    您可以通过列出内部存储的文件轻松查看 GMaps 切片缓存策略。在那里你会看到 GMaps 缓存切片。

  4. 是的,当停止/启动时,GoogleMap 将为每个显示的图块调用 getTile(x, y, zoom)。看起来每个对 getTile 的调用都有自己的线程,所以加载时间不是问题。如果您的图块已经存储在您的设备上,则加载速度非常快。只要您以智能的方式存储数据,这真的不是问题。

  5. 我从来没有返回null。不知道在这种情况下会发生什么。也许它会触发一个被忽略的异常。请注意,GoogleMap 调用将忽略您的代码在 getTile 中生成的任何运行时异常甚至某些 java.lang.error ... //code.google.com/p/gmap...

    为了回答您的问题,我返回了“NO_TILE”对象,然后 GMap 像任何图块一样缓存它。您可以通过调用TileOverlay.clearTileCache()强制重新加载图块。

  6. 我一直在考虑这一点,但我只使用 256x256 磁贴,即使在高 DPI Nexus 10 上也足够好。我没有对这个问题进行更多调查,但可能是 GMaps 已经选择了最好的磁贴显示取决于缩放级别,前提是 256p 是相当标准的平铺尺寸。

于 2013-03-06T20:38:50.597 回答