0

最近、TileProvider コードをオフライン マップ タイル用に最適化しましたが、マップをロードした後、または CameraChange を実行した後、getTile が最大 1 分間 (場合によってはまったく) 呼び出されないという新しい問題が発生しました。

この方法で TileProvider を初期化します (これは、setUpMap()、onResume()、およびマップをリセットした場合やオフライン マップのオン/オフ設定が変更された場合に呼び出す関数内にあります):

if (mapsOn()) customOverlay = mMap.addTileOverlay(new TileOverlayOptions().tileProvider
            (new MyTileProvider())); 

(customOverlay として保存して、onStop() で customOverlay.clearTileCache() を呼び出せるようにします。そうしないと、メモリに問題があるようです。)

そして、私の TileProvider は、こちらの例に従って、zip ファイルからタイルを取得するように変更されました。

public class MyTileProvider implements TileProvider {
    private final int TILE_WIDTH = 256;
    private final int TILE_HEIGHT = 256;
    private static final int BUFFER_SIZE = 16 * 1024;
    private String pathToZipFile = MyConstants.TILE_PROVIDER_PATH_PREFIX;
    private ZipResourceFile zipFile;
    private String currentPath;

    public MyTileProvider()  {
    }

    public Tile getTile(int x, int y, int zoom)  {  
//debug code here shows this is not getting called when the maps are not loading. 
//How do I force it to be called?
        byte[] image = readTileImage(x, y, zoom);
        return image == null ? NO_TILE : new Tile (TILE_WIDTH, TILE_HEIGHT, image);
    }

    private byte[] readTileImage(int x, int y, int zoom)  {
        InputStream in = null;
        ByteArrayOutputStream buffer = null;

        if (zipFile==null) initializeZipFile(x, zoom);

        try {
            in = zipFile.getInputStream(zoom+"/"+x+"/"+y+".png");
            buffer = new ByteArrayOutputStream();
            int nRead;
            byte[] data = new byte[BUFFER_SIZE];

            while ((nRead = in.read(data, 0, BUFFER_SIZE)) != -1) {
                buffer.write(data, 0, nRead);
            }                
            buffer.flush();
            return buffer.toByteArray();

        } catch (IOException e1) {      
            e1.printStackTrace();
            return null;
        } catch (OutOfMemoryError e)  {
            e.printStackTrace();
            return null;
        } finally  {
            if (in!=null) try { in.close(); } catch (Exception ignored)  {}
            if (buffer != null)  try { buffer.close();  } catch (Exception ignored) {}
        }       
    }

    public void initializeZipFile(int x, int zoom)  {       
            //code to choose the correct zip file based upon the zoom level and x coordinate
    }
}
4

2 に答える 2

1

「@Override」宣言を使用してください。

  @Override
    public Tile getTile(int x, int y, int zoom) {...}
于 2015-07-23T11:52:14.713 に答える
0

あなたのコードには論理的かつ技術的な欠陥があると思います:

論理的なもの: x および zoom パラメータに応じて異なるファイルがありますが、
1 つの変数zipFileを使用しています。したがって、zipFile != nullの場合でも、間違ったコンテンツが含まれている可能性があります。

たとえば、x=1 で zoom=1 のファイルをロードした場合、zoom が 2 に変更されても、このファイルを引き続き使用します。したがって、null をチェックするだけでは十分ではありません。

技術的なもの:
TileProvider はスレッドセーフでなければなりません。これは、コーディングには当てはまりません。readTileImage メソッドに同期を追加するだけです。しかし、これはおそらく読み込みプロセス全体を遅くし、readTileImage が呼び出されるたびにストリームをリセットしないと機能しません。したがって、ストリームの「キャッシュ」はあまり役に立ちません。同じファイル内の同じ x とズーム レベルのすべての y 座標を持つことで、タイルを整理する方法が複雑になると思います。マップは、異なる x 値と y 値のタイルを並行して読み込もうとします。同じストリームを使用してこれを実現する方法がわかりません。x、y、およびズーム トリプルごとに個別のファイルを保持します。

于 2013-10-25T06:41:52.540 に答える