39

マップの上に表示する動的なタイル コンテンツがいくつかあります (具体的には、気象画像 -- レーダー、衛星、気温など)。Google Maps API for Android v2 を使用しています。

私が抱えている問題は、明らかにタイル画像を更新する唯一の方法 (つまり、新しいデータが到着したとき、またはタイム ラプス アニメーションでフレームが進んだとき) は、TileOverlay.clearImageCache を呼び出すことです。残念ながら、これを行うと、タイル オーバーレイが一瞬ちらつきます。これは、clearImageCache が既存のタイル イメージを表示からすぐに削除するためですが、新しいタイル イメージをデコードして表示できるようになるまでに遅延が生じるためです。

毎回サーバーからタイル画像を取得するのではなく、タイル画像をキャッシュするカスタム TileProvider を使用しています。しかし、キャッシュされたタイルのみをフィードしている場合 (つまり、TileProvider.getTile の実装によって大幅な遅延が発生していない場合) であっても、プロセスには十分な遅延があり、ユーザーがちらつくことがあります。

このちらつきを回避する方法を知っている人はいますか? タイル オーバーレイをダブル バッファリングする方法はありますか? マップに 2 つの TileOverlay をアタッチしてダブル バッファリングしようとしましたが、そのうちの 1 つは非表示です。しかし、非表示の TileOverlay は、clearImageCache を呼び出した後でも、TileProvider からタイルのフェッチを開始しません。

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

私のために働いた解決策(毎秒タイルを更新しようとしました):

    // 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

したがって、一度に 2 つのレイヤーがあります (1 つは表示され、もう 1 つは表示されません)。それがパフォーマンスにどのように影響するかはわかりません。

于 2021-04-16T08:29:57.200 に答える