0

我最近优化了我的 TileProvider 代码以用于离线地图平铺,但我遇到了一个新问题,即在加载地图或跟随 CameraChange 之后,getTile 可能在一分钟内都不会被调用——有时甚至永远不会被调用。

我以这种方式初始化 TileProvider(这是在 setUpMap()、onResume() 中以及在我重置地图或我的离线地图的开/关设置更改时调用的函数中):

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

(我保存为 customOverlay 以便我可以在 onStop() 中调用 customOverlay.clearTileCache() ,否则我似乎有内存问题。)

我的 TileProvider,按照此处的示例,修改为从 zipfile 中获取图块:

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

我认为您的代码存在逻辑和技术缺陷:

合乎逻辑的一个:
您使用的是一个变量zipFile,尽管您有不同的文件,具体取决于 x 和 zoom 参数。所以即使在zipFile != null的情况下,它也可能包含错误的内容。

例如,如果您已经为假设 x=1 和 zoom=1 加载了文件,您将继续使用此文件,即使缩放更改为 2。因此仅检查 null 是不够的。

技术之一:
TileProvider 必须是线程安全的。在您的编码中不是这种情况。您可以将同步添加到您的 readTileImage 方法。但这可能会减慢整个加载过程,并且每次调用 readTileImage 时如果不重置流,它仍然无法工作。所以流的“缓存”没有多大帮助。我认为您组织图块的方式,通过在同一个文件中具有相同 x 和缩放级别的所有 y 坐标使事情变得复杂。地图将尝试并行加载不同 x 和 y 值的图块。我看不到,如何使用相同的流来完成。我会为每个 x、y 和缩放三倍保留一个单独的文件。

于 2013-10-25T06:41:52.540 回答