在osmdroid中下载titleSource的地图碎片title文件是否缓存的以及缓存大小的问题:
1.针对osmdroid的title文件缓存规律如下,第一次请求之后,缓存保存一定日期之后删除。
具体代码参考如下:
public class MapTileDownloader extends MapTileModuleProviderBase
- private class TileLoader extends MapTileModuleProviderBase.TileLoader {
- @Override
- public Drawable loadTile(final MapTileRequestState aState) throws CantContinueException {
- if (mTileSource == null) {
- return null;
- }
- InputStream in = null;
- OutputStream out = null;
- final MapTile tile = aState.getMapTile();
- try {
- if (mNetworkAvailablityCheck != null
- && !mNetworkAvailablityCheck.getNetworkAvailable()) {
- if (DEBUGMODE) {
- logger.debug("Skipping " + getName() + " due to NetworkAvailabliltyCheck.");
- }
- return null;
- }
- final String tileURLString = mTileSource.getTileURLString(tile);
- if (DEBUGMODE) {
- logger.debug("Downloading Maptile from url: " + tileURLString);
- }
- if (TextUtils.isEmpty(tileURLString)) {
- return null;
- }
- final HttpClient client = new DefaultHttpClient();
- final HttpUriRequest head = new HttpGet(tileURLString);
- final HttpResponse response = client.execute(head);
- // Check to see if we got success
- final org.apache.http.StatusLine line = response.getStatusLine();
- if (line.getStatusCode() != 200) {
- logger.warn("Problem downloading MapTile: " + tile + " HTTP response: " + line);
- return null;
- }
- final HttpEntity entity = response.getEntity();
- if (entity == null) {
- logger.warn("No content downloading MapTile: " + tile);
- return null;
- }
- in = entity.getContent();
- final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
- out = new BufferedOutputStream(dataStream, StreamUtils.IO_BUFFER_SIZE);
- StreamUtils.copy(in, out);
- out.flush();
- final byte[] data = dataStream.toByteArray();
- final ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
- // Save the data to the filesystem cache
- if (mFilesystemCache != null) {
- mFilesystemCache.saveFile(mTileSource, tile, byteStream);
- byteStream.reset();
- }
- final Drawable result = mTileSource.getDrawable(byteStream);
- return result;
- } catch (final UnknownHostException e) {
- // no network connection so empty the queue
- logger.warn("UnknownHostException downloading MapTile: " + tile + " : " + e);
- throw new CantContinueException(e);
- } catch (final LowMemoryException e) {
- // low memory so empty the queue
- logger.warn("LowMemoryException downloading MapTile: " + tile + " : " + e);
- throw new CantContinueException(e);
- } catch (final FileNotFoundException e) {
- logger.warn("Tile not found: " + tile + " : " + e);
- } catch (final IOException e) {
- logger.warn("IOException downloading MapTile: " + tile + " : " + e);
- } catch (final Throwable e) {
- logger.error("Error downloading MapTile: " + tile, e);
- } finally {
- StreamUtils.closeStream(in);
- StreamUtils.closeStream(out);
- }
- return null;
- }
首先采用在第一次请求地图的碎片时候,通过httpclient下载相关的碎片,下载成功之后,mFilesystemCache 是一个文件系统缓存处理器,缓存访问过的 地图碎片信息。
文件系统缓存器IFilesystemCache的一个具体实现如下:
public class TileWriter implements IFilesystemCache, OpenStreetMapTileProviderConstants
- public class TileWriter implements IFilesystemCache, OpenStreetMapTileProviderConstants {
- // ===========================================================
- // Constants
- // ===========================================================
- private static final Logger logger = LoggerFactory.getLogger(TileWriter.class);
- // ===========================================================
- // Fields
- // ===========================================================
- /** amount of disk space used by tile cache **/
- private static long mUsedCacheSpace;
- // ===========================================================
- // Constructors
- // ===========================================================
- public TileWriter() {
- // do this in the background because it takes a long time
- final Thread t = new Thread() {
- @Override
- public void run() {
- mUsedCacheSpace = 0; // because it's static
- calculateDirectorySize(TILE_PATH_BASE);
- if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {
- cutCurrentCache();
- }
- if (DEBUGMODE) {
- logger.debug("Finished init thread");
- }
- }
- };
- t.setPriority(Thread.MIN_PRIORITY);
- t.start();
- }
- // ===========================================================
- // Getter & Setter
- // ===========================================================
- /**
- * Get the amount of disk space used by the tile cache. This will initially be zero since the
- * used space is calculated in the background.
- *
- * @return size in bytes
- */
- public static long getUsedCacheSpace() {
- return mUsedCacheSpace;
- }
- // ===========================================================
- // Methods from SuperClass/Interfaces
- // ===========================================================
- @Override
- public boolean saveFile(final ITileSource pTileSource, final MapTile pTile,
- final InputStream pStream) {
- final File file = new File(TILE_PATH_BASE, pTileSource.getTileRelativeFilenameString(pTile)
- + TILE_PATH_EXTENSION);
- final File parent = file.getParentFile();
- if (!parent.exists() && !createFolderAndCheckIfExists(parent)) {
- return false;
- }
- BufferedOutputStream outputStream = null;
- try {
- outputStream = new BufferedOutputStream(new FileOutputStream(file.getPath()),
- StreamUtils.IO_BUFFER_SIZE);
- final long length = StreamUtils.copy(pStream, outputStream);
- mUsedCacheSpace += length;
- if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {
- cutCurrentCache(); // TODO perhaps we should do this in the background
- }
- } catch (final IOException e) {
- return false;
- } finally {
- if (outputStream != null) {
- StreamUtils.closeStream(outputStream);
- }
- }
- return true;
- }
- // ===========================================================
- // Methods
- // ===========================================================
- private boolean createFolderAndCheckIfExists(final File pFile) {
- if (pFile.mkdirs()) {
- return true;
- }
- if (DEBUGMODE) {
- logger.debug("Failed to create " + pFile + " - wait and check again");
- }
- // if create failed, wait a bit in case another thread created it
- try {
- Thread.sleep(500);
- } catch (final InterruptedException ignore) {
- }
- // and then check again
- if (pFile.exists()) {
- if (DEBUGMODE) {
- logger.debug("Seems like another thread created " + pFile);
- }
- return true;
- } else {
- if (DEBUGMODE) {
- logger.debug("File still doesn't exist: " + pFile);
- }
- return false;
- }
- }
- private void calculateDirectorySize(final File pDirectory) {
- final File[] z = pDirectory.listFiles();
- if (z != null) {
- for (final File file : z) {
- if (file.isFile()) {
- mUsedCacheSpace += file.length();
- }
- if (file.isDirectory() && !isSymbolicDirectoryLink(pDirectory, file)) {
- calculateDirectorySize(file); // *** recurse ***
- }
- }
- }
- }
- /**
- * Checks to see if it appears that a directory is a symbolic link. It does this by comparing
- * the canonical path of the parent directory and the parent directory of the directory's
- * canonical path. If they are equal, then they come from the same true parent. If not, then
- * pDirectory is a symbolic link. If we get an exception, we err on the side of caution and
- * return "true" expecting the calculateDirectorySize to now skip further processing since
- * something went goofy.
- */
- private boolean isSymbolicDirectoryLink(final File pParentDirectory, final File pDirectory) {
- try {
- final String canonicalParentPath1 = pParentDirectory.getCanonicalPath();
- final String canonicalParentPath2 = pDirectory.getCanonicalFile().getParent();
- return !canonicalParentPath1.equals(canonicalParentPath2);
- } catch (final IOException e) {
- return true;
- } catch (final NoSuchElementException e) {
- // See: http://code.google.com/p/android/issues/detail?id=4961
- // See: http://code.google.com/p/android/issues/detail?id=5807
- return true;
- }
- }
- private List<File> getDirectoryFileList(final File aDirectory) {
- final List<File> files = new ArrayList<File>();
- final File[] z = aDirectory.listFiles();
- if (z != null) {
- for (final File file : z) {
- if (file.isFile()) {
- files.add(file);
- }
- if (file.isDirectory()) {
- files.addAll(getDirectoryFileList(file));
- }
- }
- }
- return files;
- }
- /**
- * If the cache size is greater than the max then trim it down to the trim level. This method is
- * synchronized so that only one thread can run it at a time.
- */
- private void cutCurrentCache() {
- synchronized (TILE_PATH_BASE) {
- if (mUsedCacheSpace > TILE_TRIM_CACHE_SIZE_BYTES) {
- logger.info("Trimming tile cache from " + mUsedCacheSpace + " to "
- + TILE_TRIM_CACHE_SIZE_BYTES);
- final List<File> z = getDirectoryFileList(TILE_PATH_BASE);
- // order list by files day created from old to new
- final File[] files = z.toArray(new File[0]);
- Arrays.sort(files, new Comparator<File>() {
- @Override
- public int compare(final File f1, final File f2) {
- return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
- }
- });
- for (final File file : files) {
- if (mUsedCacheSpace <= TILE_TRIM_CACHE_SIZE_BYTES) {
- break;
- }
- final long length = file.length();
- if (file.delete()) {
- mUsedCacheSpace -= length;
- }
- }
- logger.info("Finished trimming tile cache");
- }
- }
- }
- }
在TileWriter 文件缓存器创建的时候,
1.创建一个线程检查相关的文件大小
代码如下:
- public TileWriter() {
- // do this in the background because it takes a long time
- final Thread t = new Thread() {
- @Override
- public void run() {
- mUsedCacheSpace = 0; // because it's static
- calculateDirectorySize(TILE_PATH_BASE);
- if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {
- cutCurrentCache();
- }
- if (DEBUGMODE) {
- logger.debug("Finished init thread");
- }
- }
- };
- t.setPriority(Thread.MIN_PRIORITY);
- t.start();
- }
2.在缓存中保存文件缓存的过程如下:
- @Override
- public boolean saveFile(final ITileSource pTileSource, final MapTile pTile,
- final InputStream pStream) {
- final File file = new File(TILE_PATH_BASE, pTileSource.getTileRelativeFilenameString(pTile)
- + TILE_PATH_EXTENSION);
- final File parent = file.getParentFile();
- if (!parent.exists() && !createFolderAndCheckIfExists(parent)) {
- return false;
- }
- BufferedOutputStream outputStream = null;
- try {
- outputStream = new BufferedOutputStream(new FileOutputStream(file.getPath()),
- StreamUtils.IO_BUFFER_SIZE);
- final long length = StreamUtils.copy(pStream, outputStream);
- mUsedCacheSpace += length;
- if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {
- cutCurrentCache(); // TODO perhaps we should do this in the background
- }
- } catch (final IOException e) {
- return false;
- } finally {
- if (outputStream != null) {
- StreamUtils.closeStream(outputStream);
- }
- }
- return true;
- }
3.清理文件缓存的方法实现如下:
- /**
- * If the cache size is greater than the max then trim it down to the trim level. This method is
- * synchronized so that only one thread can run it at a time.
- */
- private void cutCurrentCache() {
- synchronized (TILE_PATH_BASE) {
- if (mUsedCacheSpace > TILE_TRIM_CACHE_SIZE_BYTES) {
- logger.info("Trimming tile cache from " + mUsedCacheSpace + " to "
- + TILE_TRIM_CACHE_SIZE_BYTES);
- final List<File> z = getDirectoryFileList(TILE_PATH_BASE);
- // order list by files day created from old to new
- final File[] files = z.toArray(new File[0]);
- Arrays.sort(files, new Comparator<File>() {
- @Override
- public int compare(final File f1, final File f2) {
- return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
- }
- });
- for (final File file : files) {
- if (mUsedCacheSpace <= TILE_TRIM_CACHE_SIZE_BYTES) {
- break;
- }
- final long length = file.length();
- if (file.delete()) {
- mUsedCacheSpace -= length;
- }
- }
- logger.info("Finished trimming tile cache");
- }
- }
- }
由上述代码可以看出:看出缓存大于最大值时候清理缓存
- /** 30 days */
- public static final long TILE_EXPIRY_TIME_MILLISECONDS = 1000L * 60 * 60 * 24 * 30;
- /** 600 Mb */
- public static final long TILE_MAX_CACHE_SIZE_BYTES = 600L * 1024 * 1024;
- /** 500 Mb */
- public static final long TILE_TRIM_CACHE_SIZE_BYTES = 500L * 1024 * 1024;
- if (mUsedCacheSpace > TILE_MAX_CACHE_SIZE_BYTES) {
- cutCurrentCache(); // TODO perhaps we should do this in the background
- }
原文:http://topmanopensource.iteye.com/blog/1664631
相关推荐
加载GeoPackage离线底图到osmdroid中,首先需要确保你的项目已经正确集成osmdroid库。通常,这可以通过在build.gradle文件中添加osmdroid依赖来实现。例如: ```groovy dependencies { implementation 'org....
在深入研究Osmdroid源码时,你需要关注以下几个关键模块: 1. **MapView**:这是Osmdroid的核心组件,它负责地图的显示和用户交互。在源码中,你可以看到如何处理触控事件,以及如何更新地图视图。 2. **TileSource*...
通过研究TileSource的源码,我们可以学习到如何在Java环境中构建一个基本的游戏GUI,理解图块化布局的实现,以及游戏开发中的一些核心概念。同时,这也为我们提供了一个实践Java GUI编程和游戏开发的实例。
在Xamarin中,我们可以利用Java Bindings Library将Java库(如osmdroid-android-binding-4.2)转化为C#代码,以便在Xamarin.Android项目中使用。 要创建这个简单的地图Demo,首先需要在Xamarin项目中添加osmdroid库...
在8.24这个阶段的学习中,可能涉及到的关键技术点包括: 1. **地图瓦片(Tile)渲染**:OpenScales支持瓦片地图服务,如OpenStreetMap或Google Maps,通过将大地理区域分割成小块(瓦片)来高效加载和显示地图。这...
在IT行业中,尤其是在地理信息系统(GIS)领域,海图数据的处理和可视化是至关重要的。本文将详细讲解如何将S57格式的海图数据转换为TMS(Tile Map Service)瓦片,并将其加载到osgearth这个开源的地球可视化框架中...
在IT行业中,VB(Visual Basic)是一种经典的...通过这个项目,开发者可以学习到如何将GIS功能集成到桌面应用中,以及如何创建交互式的地图导航工具。对于有兴趣在GIS领域进行开发的人来说,这是一个很好的实践项目。
GeoWebCache(GWC)是一种基于开源地理信息系统(GIS)软件GeoServer的缓存服务,它能够预先生成地图切片并存储在本地或分布式存储系统中,以提高...通过研究源码,你可以更深入地理解上述知识点,并学习如何实际应用。
在这个示例中,开发者可以学习如何初始化地图控件,设置中心点、缩放级别,以及添加图层和标记。 地图控件是WP8地图API的核心组件,用于在应用程序中显示地图。通过设置MapControl的Center属性,可以改变地图的中心...
OpenLayers 3 是一个强大的...总的来说,OpenLayers 3 源码研究涉及地图绘制、数据处理、用户交互等多个方面,对提升GIS开发技能大有裨益。通过深入理解并实践,开发者可以构建出功能强大、用户体验优秀的Web地图应用。
在IT行业中,地图服务是许多应用的核心组成部分,特别是在地理信息系统(GIS)中。OpenLayers是一个流行的开源JavaScript库,用于在Web浏览器中展示地图。而ArcGIS则是Esri公司提供的一个全面的GIS平台,包括在线...
OpenLayers 是一个开源JavaScript库,专门用于...以上只是OpenLayers 2.9.1 API的部分关键知识点,实际使用中,开发者还需要参考apidocs中的详细文档,理解各个类、方法和属性的具体用法,以充分利用这个强大的GIS库。
在IT行业中,地图渲染是数据可视化的一个重要领域,OpenLayers 和 ECharts 都是流行的开源库,分别在Web GIS和数据图表展示上有着广泛的应用。本文将深入探讨如何利用OpenLayers加载Echarts省市轮廓,并通过XYZ方式...
在IT领域,尤其是在地理信息系统(GIS)中,加载本地离线影像瓦片地图是一个常见的需求。osgEarth是一个基于OpenSceneGraph(OSG)的开源库,它提供了将2D地图和3D地形集成到实时3D场景中的能力。本教程将深入探讨...
瓦片地图下载,免安装,可兼容OpenLayer,这一主题涉及到的是Web地图开发中的关键技术和工具。瓦片地图是一种常见的在线地图展示方式,它将大范围、高分辨率的地图分割成多个小块(通常为256x256像素的图片),每个...
要加载本地切片,你需要创建一个TileSource实例,然后将其添加到Map对象中。这里是一个基本示例: ```javascript // 创建一个新的OpenLayers Map对象 var map = new ol.Map({ target: 'map', // 指定地图容器的...
在这个DEMO中,我们重点关注两个关键点:地图瓦片的组织和OpenLayers的配置。 1. **地图瓦片的组织**: 地图瓦片通常按照一定的网格系统进行分块,如XYZ网格(X、Y轴坐标和Zoom级别)。每个瓦片都是一个固定大小...
《Python库:深入理解large-image-source-pil》 在Python的世界里,库是开发者们的重要工具...无论是在科学研究、地图制图,还是在医疗影像分析等领域,这个库都能发挥重要作用,帮助开发者更好地应对大型图像的挑战。
在IT行业中,地图服务的开发和应用是GIS(地理信息系统)领域的重要组成部分。OpenLayers是一个流行的JavaScript库,用于创建交互式地图应用,而GeoServer是一个开源的WMS(Web Map Service)服务器,它允许发布和...
OpenLayers 是一个强大的开源JavaScript库,用于在网页上创建交互式的地图应用。它支持多种地图服务,包括WMS...通过学习和理解这个DEMO,你可以进一步掌握OpenLayers的操作,并将其应用到更复杂和定制化的地图项目中。