39

我有一些动态图块内容要显示在地图上(特别是天气图像——雷达、卫星、温度等)。我正在使用适用于 Android v2 的 Google Maps API。

我遇到的问题是,显然更新平铺图像的唯一方法(即当新数据到达时,或者当帧在延时动画中前进时)是调用 TileOverlay.clearImageCache。不幸的是,当我这样做时,瓷砖覆盖片会闪烁片刻。这是因为 clearImageCache 会立即从显示中删除现有的平铺图像,但在解码和显示新的平铺图像之前存在延迟。

我正在使用自定义 TileProvider 来缓存平铺图像,而不是每次都从服务器获取它们。但即使它只提供缓存的切片(即我的 TileProvider.getTile 实现没有造成明显的延迟),在处理过程中仍然有足够的延迟,用户可以看到闪烁。

有谁知道避免这种闪烁的方法?有什么方法可以对瓷砖叠加层进行双重缓冲?我尝试使用附加到地图的两个 TileOverlay 对其进行双重缓冲,其中一个是不可见的。但是不可见的 TileOverlay 并没有开始从我的 TileProvider 中获取任何图块——即使在我调用 clearImageCache 之后也是如此。

4

4 回答 4

1

是否可以加载即将到来的平铺图像但是将可见性设置为 false?Tile.setVisible(false);

然后当你想改变时(在即将到来的瓦片加载后),将即将到来的瓦片设置为可见而当前瓦片不可见?

CurrentTile.setVisible(false);
NewTile.setVisible(true);

这样,更改都发生在同一个渲染帧内,并且没有等待缓存图像加载的延迟。

于 2013-03-07T04:33:26.297 回答
0

一个相当好的解决方案是将切片下载和缓存与 TileProvider 分开。这样您就可以完全控制何时下载它们,并且仅在下载全部后替换 byte[] 引用。

这可能有点复杂,因为您必须注意当前的可见区域并缩放而不是全部下载它们,而只下载那些可见的区域。

编辑

使用以下代码进行测试:

try {
    InputStream is = getAssets().open("tile1.jpg");
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int b = is.read();
    while (b != -1) {
        baos.write(b);
        b = is.read();
    }
    byte[] array = baos.toByteArray();
    cache = new Tile(256, 256, array);
    is = getAssets().open("tile2.jpg");
    baos = new ByteArrayOutputStream();
    b = is.read();
    while (b != -1) {
        baos.write(b);
        b = is.read();
    }
    array = baos.toByteArray();
    nextCache = new Tile(256, 256, array);
} catch (IOException ex) {
    Log.e("tag", "error reading tiles", ex);
}

tileOverlay = map.addTileOverlay(new TileOverlayOptions().tileProvider(new TileProvider() {
    @Override
    public Tile getTile(int x, int y, int zoom) {
        return cache;
    }
}));

稍后的某个地方:

Tile temp = cache;
cache = nextCache;
nextCache = temp;
tileOverlay.clearTileCache();

“最快”的可能代码仍然失败。

如果您无法切换到 GroundOverlay 或 Markers,另一个想法是尝试使用第三方地图图块,即您当前的天气图块上方和下一个图块,以便他们可以在几秒钟后加载和切换它们(使用 zOrder)。

于 2013-03-21T07:14:30.757 回答
0

我为此找到的解决方案是使图层的透明度为 1。这使它们隐藏但仍然请求图块。然后,您可以切换哪些图层的透明度为 1 和 0。

由于在更改两个图层的透明度之间进行了渲染调用,仍然存在一些闪烁的可能性。没有办法使它成为原子操作。

还发现没有一种很好的方法可以知道图层何时完全加载了图块。即使在您从 TileProvider 返回图块之后,Google 地图也必须对其进行一些处理,因此您在切换图块之前需要一些延迟。

于 2020-08-30T01:14:28.123 回答
0

对我有用的解决方案(我尝试每秒刷新瓷砖):

    // Adding "invisible" overlay
    val newTileOverlay =  mMap?.addTileOverlay(
        TileOverlayOptions()
            .tileProvider(getTileProvider()).transparency(1f).visible(true)
    )

    mTileOverlay?.transparency = 0.5f // making previous overlay visible
    mOldTileOverlay?.remove() // removing previously displayed visible overlay
    mOldTileOverlay = mTileOverlay
    mTileOverlay = newTileOverlay

所以我们一次有两层(一层可见,一层不可见)。我不确定它如何影响性能。

于 2021-04-16T08:29:57.200 回答