我有一些动态图块内容显示在地图上(特别是天气图像 - 雷达,卫星,温度等)。我正在使用Google Maps API for Android v2。
我遇到的问题显然是更新磁贴图像的唯一方法(即当新数据到达时,或者帧在时间推移动画中前进时)是调用TileOverlay.clearImageCache。不幸的是,当我这样做时,瓷砖覆盖层会闪烁一会儿。这是因为clearImageCache会立即从显示中删除现有的图块图像,但在解码和显示新的图块图像之前会有一段延迟。
我正在使用自定义TileProvider来缓存切片图像,而不是每次都从服务器中获取它们。但即使它只提供缓存的磁贴(即我的TileProvider.getTile实现没有明显的延迟),用户仍然可以看到闪烁的延迟。
有谁知道避免这种闪烁的方法?有什么方法可以双重缓冲瓷砖覆盖?我尝试使用附加到地图的两个TileOverlay对其进行双缓冲,其中一个是不可见的。但是,即使在我调用clearImageCache之后,看不见的TileOverlay也没有开始从我的TileProvider中获取任何图块。
答案 0 :(得分:1)
是否可以加载即将发布的图块但是可见性设置为false? Tile.setVisible(false);
然后当您想要更改时(在即将加载的图块之后),将即将显示的图块设置为可见并且当前图块是不可见的?
CurrentTile.setVisible(false);
NewTile.setVisible(true);
这种方式更改都发生在同一个渲染帧中,并且没有延迟等待缓存的图像加载。
答案 1 :(得分: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)。
答案 2 :(得分:0)
为此,我找到的解决方案是使图层的透明度为1。这使它们隐藏但仍在请求拼贴。然后,您可以切换透明度为1和0的图层。
由于在两层透明度的更改之间进行了一次渲染调用,因此仍有一些闪烁的可能性。没有办法使它成为原子操作。
还发现,没有什么好方法可以知道图层何时完全加载了图块。即使您从TileProvider返回了图块,Google Maps也必须对其进行一些处理,因此在切换图块之前您需要一些延迟。
答案 3 :(得分: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
所以我们一次有两层(一层可见,一层不可见)。我不确定它如何影响性能。