Как обновить TileOverlay без мерцания?
У меня есть динамическое содержимое плитки для отображения поверх карты (в частности, погодные изображения - радар, спутник, температура и т.д.). Я использую API Карт Google для Android v2.
Проблема, с которой я сталкиваюсь, заключается в том, что, по-видимому, единственный способ обновить изображения с черепицей (т.е. когда новые данные поступают или когда кадр продвигается в анимации с временной задержкой) заключается в вызове TileOverlay.clearImageCache. К сожалению, когда я это делаю, наложение на плитки мерцает на мгновение. Это связано с тем, что clearImageCache немедленно удаляет существующие изображения с экрана, но есть задержка, прежде чем он сможет декодировать и отображать новые изображения в виде плитки.
Я использую пользовательский TileProvider, который кэширует изображения с фрагментами, а не извлекает их с сервера каждый раз. Но даже когда он подает только кешированные фрагменты (т.е. Не существует значительной задержки, наложенной моей реализацией TileProvider.getTile), все еще достаточно задержки в процессе, когда пользователь может видеть мерцание.
Кто-нибудь знает, как избежать этого мерцания? Есть ли способ удвоить буфер наложения плитки? Я попытался удвоить буфер с двумя TileOverlays, прикрепленными к карте, одна из которых невидима. Но невидимый TileOverlay не начинает получать какие-либо фрагменты из моего TileProvider - даже после вызова clearImageCache.
Ответы
Ответ 1
Можно ли загружать изображение будущей плитки, но имеет ли видимость значение false? Tile.setVisible(false);
Затем, когда вы хотите изменить (после того, как наступающая плитка загрузилась), установите предстоящую плитку видимой, а текущая плитка будет невидимой?
CurrentTile.setVisible(false);
NewTile.setVisible(true);
Таким образом, все изменения происходят внутри одного кадра рендеринга, и нет никакой задержки, ожидающей загрузки кэшированных изображений.
Ответ 2
Довольно хорошим решением было бы отделить загрузку и кеширование от TileProvider. Таким образом, вы можете полностью контролировать их загрузку и заменять только байты [] после загрузки всех.
Это может быть немного сложнее, потому что вам нужно позаботиться о текущей видимой области и увеличить, чтобы не загружать их все, но только те, которые будут видны.
Edit
Протестировано следующим кодом:
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) через несколько секунд.